在实际工作中,发现大学C++教科书上的C++知识还不够用,或者理解不够深,为此这方面还得冲冲电。下面是简单整理了以前不太熟悉的几个点。
1. 构造和拷贝函数
l 赋值构造函数:T(T &)
l 赋值拷贝函数: operator = (T &)
l 移动构造函数: T(T &&)
l 移动拷贝函数:operator =(T&&)
一般如果类中有指针成员,建议 disable 掉赋值构造和赋值拷贝函数。而通常出于对性能优化的目的,可以使用移动构造函数和移动拷贝函数来减少冗余拷贝。
举例说明:
class T {
T(int);
T(const T&);
Operator = (const T&);
T(const T&&);
}
int main() {
T a = T(1);
T && b = T(2);
}
上面T a 的初始化过程中,有一次构造一次拷贝;而T b就只有一次构造了。
2. virtual
l 限定虚函数:virtual func(….) ;
l 限定纯虚函数: virtual func(….) =0 , 抽象类只有纯虚函数
l 限定被继承的基类,用作虚基类,避免子类拥有基类中重复的成员方法;
例如: class B: virtual A;
class C: virtual A;
class D: class B, class C; // 那么D的对象中只有A的一份成员;
l 抽象类的析构函数一定是虚函数(个人的理解是对于里面的虚函数可能用到的资源是不定的)
3. C++ 11 中的自动推断变量类型auto 的使用
Auto 的使用极大地方便了枚举器的使用,隐藏了枚举的过程,举例如下:
Auto x1=3.1415169;
Std::map<float, int> mymap;
For (auto it = mymap.begin; it != mymap.end(); it++) {
……
}
4. C++ 匿名函数 lamnda 的使用
本质就是去类临时函数定义时的名称,通过【】代替。这种函数通常在一些算法库中的比较函数、判断是否相等的临时函数的定义中。
格式如下:
[capture](parameters)->return-type{body}
其中capture高速这个临时函数,是否以及如何使用外部的变量,规则如下:
[] //未定义变量.试图在Lambda内使用任何外部变量都是错误的.
[x, &y] //x 按值捕获, y 按引用捕获.
[&] //用到的任何外部变量都隐式按引用捕获
[=] //用到的任何外部变量都隐式按值捕获
[&, x] //x显式地按值捕获. 其它变量按引用捕获
[=, &z] //z按引用捕获. 其它变量按值捕获
实例如下:
【】(int a, int b)->int (int z= a+b; return z);
5. 构造函数和析构函数执行的顺序
具体规则如下:
l 如果对象的类型是global/static 等落在.data或者.bss段,那么对于global的变量,先于main()函数执行构造;对于function domain的则在执行到的地方开始执行构造。析构函数按镜像对称的顺序进行;
l 如果对象的类型是在栈上,在执行到代码的地方开始构造,在作用域结束的地方析构;
l 如果对象的类型在堆上,根据显式调用析构函数的顺序执行;如果没有显式调用析构,在堆被系统释放的时候调用析构函数;
l 对于多重继承的情况,构造函数沿着从基类到子类的方向进行,而析构函数沿着相反方向执行。