-
C++ 中使用 cout 输出 bool 变量的值时还是用数字 1 和 0 表示,而不是 true 或 false。(C++ 中 非0即1(只用数值0/false是0,其他全是1))
-
new 和 delete、new[] 和 delete[] *** 作符应该成对出现,并且不要和C语言中 malloc()、free() 一起混用。
-
为了消除函数调用的时空开销,C++ 提供一种提高效率的方法,即在编译时将函数调用处用函数体替换,类似于C语言中的宏展开。这种在函数调用处直接嵌入函数体的函数称为内联函数(Inline Function),又称内嵌函数或者内置函数。(在函数前加上关键字 inline 即可(要在函数定义处添加 inline 关键字,在函数声明处添加 inline 关键字虽然没有错,但这种做法是无效的,编译器会忽略函数声明处的 inline 关键字。))
-
当函数比较复杂时,函数调用的时空开销可以忽略,大部分的 CPU 时间都会花费在执行函数体代码上,所以我们一般是将非常短小的函数声明为内联函数。
-
C++规定,默认参数只能放在形参列表的最后,而且一旦为某个形参指定了默认值,那么它后面的所有形参都必须有默认值。实参和形参的传值是从左到右依次匹配的,默认参数的连续性是保证正确传参的前提。
// 正确
void func(int a, int b=10, int c=20){ }
void func(int a, int b, int c=20){ }
// 错误
void func(int a, int b=10, int c=20, int d){ }
void func(int a, int b=10, int c, int d=20){ }
- 参数列表又叫参数签名,包括参数的类型、参数的个数和参数的顺序,只要有一个不同就叫做参数列表不同。
- 类名的首字母一般大写,以和其他的标识符区分开。{ }内部是类所包含的成员变量和成员函数,它们统称为类的成员
class Student{
public:
//成员变量
char *name;
int age;
float score;
//成员函数
void say(){
cout<<name<<"的年龄是"<<age<<",成绩是"<<score<<endl;
}
};
Student liLei; //创建对象
- 两种创建对象的方式:一种是在栈上创建,形式和定义普通变量类似;另外一种是在堆上使用 new 关键字创建,必须要用一个指针指向它,读者要记得 delete 掉不再使用的对象。
- 对象名字访问成员使用点号.,通过对象指针访问成员使用箭头->,这和结构体非常类似。
//创建对象
Student stu;
stu.name = "小明";
stu.age = 15;
stu.score = 92.5f;
stu.say();
Student *pStu = new Student;
pStu -> name = "小明";
pStu -> age = 15;
pStu -> score = 92.5f;
pStu -> say();
delete pStu; //删除对象
- 也可以只在类体中声明函数,而将函数定义放在类体外面(::被称为域解析符(也称作用域运算符或作用域限定符),用来连接类名和函数名,指明当前函数属于哪个类)(成员函数必须先在类体中作原型声明,然后在类外定义,也就是说类体的位置应在函数定义之前。)
class Student{
public:
//成员变量
char *name;
int age;
float score;
//成员函数
void say(); //函数声明
};
//函数定义
void Student::say(){
cout<<name<<"的年龄是"<<age<<",成绩是"<<score<<endl;
}
- 在类体中和类体外定义成员函数是有区别的:在类体中定义的成员函数会自动成为内联函数,在类体外定义的不会。当然,在类体内部定义的函数也可以加 inline 关键字,但这是多余的,因为类体内部定义的函数默认就是内联函数。
- 内联函数一般不是我们所期望的,它会将函数调用处用函数体替代,所以我建议在类体内部对成员函数作声明,而在类体外部进行定义,这是一种良好的编程习惯,实际开发中大家也是这样做的。当然,如果你的函数比较短小,希望定义为内联函数,那也没有什么不妥的。
- 类函数定义在外部也可以是内联函数
class Student{
public:
char *name;
int age;
float score;
void say(); //内联函数声明,可以增加 inline 关键字,但编译器会忽略
};
//函数定义
inline void Student::say(){
cout<<name<<"的年龄是"<<age<<",成绩是"<<score<<endl;
}
- 构造函数在实际开发中会大量使用,它往往用来做一些初始化工作,例如对成员变量赋值、预先打开文件等。
- 调用没有参数的构造函数也可以省略括号
- VLA 类包含了两个成员变量,m_len 和 m_arr 指针,需要注意的是 m_len 加了 const 修饰,只能使用初始化列表的方式赋值
class VLA{
private:
const int m_len;
int *m_arr;
public:
VLA(int len);
};
//必须使用初始化列表来初始化 m_len
VLA::VLA(int len): m_len(len){
m_arr = new int[len];
}
17.如下赋值是错误的
class VLA{
private:
const int m_len;
int *m_arr;
public:
VLA(int len);
};
VLA::VLA(int len){
m_len = len;
m_arr = new int[len];
}
- 上面我们定义了一个 VLA 类来模拟变长数组,它使用一个构造函数为数组分配内存,这些内存在数组被销毁后不会自动释放,所以非常有必要再添加一个析构函数,专门用来释放已经分配的内存。请看下面的完整示例:
#include
using namespace std;
class VLA{
public:
VLA(int len); //构造函数
~VLA(); //析构函数
public:
void input(); //从控制台输入数组元素
void show(); //显示数组元素
private:
int *at(int i); //获取第i个元素的指针
private:
const int m_len; //数组长度
int *m_arr; //数组指针
int *m_p; //指向数组第i个元素的指针
};
VLA::VLA(int len): m_len(len){ //使用初始化列表来给 m_len 赋值
if(len > 0){ m_arr = new int[len]; /*分配内存*/ }
else{ m_arr = NULL; }
}
VLA::~VLA(){
delete[] m_arr; //释放内存
}
void VLA::input(){
for(int i=0; m_p=at(i); i++){ cin>>*at(i); }
}
void VLA::show(){
for(int i=0; m_p=at(i); i++){
if(i == m_len - 1){ cout<<*at(i)<<endl; }
else{ cout<<*at(i)<<", "; }
}
}
int * VLA::at(int i){
if(!m_arr || i<0 || i>=m_len){ return NULL; }
else{ return m_arr + i; }
}
int main(){
//创建一个有n个元素的数组(对象)
int n;
cout<<"Input array length: ";
cin>>n;
VLA *parr = new VLA(n);
//输入数组元素
cout<<"Input "<<n<<" numbers: ";
parr -> input();
//输出数组元素
cout<<"Elements: ";
parr -> show();
//删除数组(对象)
delete parr;
return 0;
}
- 一个类中可以有一个或多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它。
class Student{
public:
Student(char *name, int age, float score);
void show();
public:
static int m_total; //静态成员变量
private:
char *m_name;
int m_age;
float m_score;
};
/通过类类访问 static 成员变量
Student::m_total = 10;
//通过对象来访问 static 成员变量
Student stu("小明", 15, 92.5f);
stu.m_total = 20;
//通过对象指针来访问 static 成员变量
Student *pstu = new Student("李华", 16, 96);
pstu -> m_total = 20;
- static 成员变量和普通 static 变量一样,都在内存分区中的全局数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。
- 静态成员变量必须初始化,而且只能在类体外进行。例如:
int Student::m_total = 10;
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)