1. extern
1)extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。
现代编译器一般采用按文件编译的方式,因此在编译时,全局变量的可见域限制在文件内部。到了链接阶段,要将各个文件的内容“合为一体”,定义于某文件内的全局变量,在链接完成后,它的可见范围被扩大到了整个程序。因此,如果某些文件中定义的全局变量名相同的话,在这个时候就会出现错误,也就是上面提示的重复定义的错误。
因此,各个文件中定义的全局变量名不可相同。
extern的原理很简单,就是告诉编译器:“你现在编译的文件中,有一个标识符虽然没有在本文件中定义,但是它是在别的文件中定义的全局变量,你要放行!”
注意:①在定义的时候,这个extern可以被省略。定义只能出现在一处。
②当你要引用一个全局变量的时候,你就要声明extern int a。这时候extern不能省略。
引用一个定义在其它模块的全局函数或变量(如,全局函数或变量定义在A模块,B欲引用)有两种方法,
一、B模块中include模块A的头文件。
2)extern “C”
C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数的情况,此时C++中若要使用C函数,就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。
目的:实现C++与C的混合编程。
2. 前置和后置++
后置++,会先生成一个临时对象,在对原对象+1,最后返回临时对象(右值)。
前置++,直接对原对象+1,返回对象引用(左值)。
前置++,更高效。
3. inline
inline函数会增大二进制程序的体积,但是会使执行速度加快。
同时,编译期间可以对参数进行强类型的检查,这是inline优于宏的一个方面。
inline函数中,不能递归,不能有循环、switch语句,代码行数不能太多,否则编译器不会将其展开。
(对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,所以也没有必要用内联函数实现。)
4. ifndef
条件编译
5. 重载函数
a) 函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。不能利用
返回类型进行重载。b) 类中函数const和非const可以进行重载,其实原理是利用this指针的类型是const和非const进行重载,其实原理就是参数类型不同。
6. 构造函数 和 析构函数 能否为 虚函数?
a) 虚拟析构函数的使用场景是父类指针指向子类,调用delete的时候使用虚函数(调用子类析构函数),防止部分内存泄露。
b) 构造函数不能声明为虚拟函数,因为对象的虚函数表指针其实是在构造函数内编译器添加完成的代码,所以在构造函数执行之前无法访问到虚拟函数表的。
7. 成员函数初始化列表
1) 类的static变量在类的构造函数前已进行初始化。
2) 如果无成员初始化列表,隐式初始化。按照声明的顺序依次调用所有基类的缺省构造函数,然后所有成员类对象的缺省构造函数。
3) 构造函数体内的数据成员的设置被认为赋值,而不是初始化。
4)使用初始化列表的理由:
a)const 成员、引用成员、无默认构造函数(不需要参数)的类对象成员
b)效率:未利用初始化列表而是在构造函数体内进行赋值,则调用了缺省构造函数和赋值运算符操作。如果数据成员为自定义的类对象,则效率比直接利用构造函数初始化低很多。
8.指针和引用
指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名。
引用只能并且必须在定义时被初始化一次,之后不可变。引用不能为空。
9. 类的默认生成的成员函数
构造函数,拷贝构造函数,赋值操作符,析构函数。
取地址运算符,const取地址运算符。
10. 一维数组默认初始化问题
全局和静态数组初始化为0(值初始化),否则不做初始化。
内置数据类型都如此。
11. 指针
1) const char *p1 等价于 char const *p1
char *const p2
2) 函数指针:char (*p)();
返回指针的函数:char* p();
3) 指针数组:char *a[3]; //sizeof(a)=12
数组指针:char (*p)[3]; //sizeof(p)=4
12.大小端
小端:低位低地址,高位高地址
大端:类似于把数据当作字符串
int a=1;
char c=*((char*)(&a));
if(c==1) 小端
else 大端