最近一直在看 Inside The C++ Object Model, 希望从这本书中了解一下底层对象模型的设计,也为以后研究JVM的对象模型做铺垫。
注:由于这本书比较老,最新也就是C++ 98标准。因此这些总结都是基于C++ 98标准的。如果有C++ 11中新增的特性或新的优化(貌似析构函数那一部分变了挺多),我会单独指出。
这篇将总结C++的构造函数语义学相关的内容( Inside The C++ Object Model, Chapter 2 )。第二章主要讲述了构造函数的相关模型及事项。
Implicit Default Constructor(C++ 98)
在我们没有声明默认构造函数的时候,编译器有可能会为我们自动生成默认构造函数。不过,并非在所有情况下,编译器都自动生成default constructor。当且仅当以下四种情况下,编译器会自动为一个类生成default constructor:
- 此类有一个显式地实现了默认构造函数(explicit default constructor)的对象成员变量
- 此类的父类显式地实现了默认构造函数
- 此类中存在虚函数
- 此类间接继承了虚基类
注: C++ 11标准增加了移动构造函数(move constructor),有关移动构造函数相关的东西可以看C++ 11标准。
Copy Constructor(C++ 98)
No Bitwise copy
编译器不能简单地拷贝对象,因为编译器需要保证vptr
和vtbl
的正确性。复制的时候要注意正确赋值。比如:
|
|
如果在赋值的时候将sub object赋值给base object,编译器为了确保vptr
和vtbl
的一致性,会对其截断:
|
|
Return Value Initialization (Traditional C++)
注:C++ 11以后引入了Copy Elision可以省掉copy的过程。
|
|
经过编译器解析后被转化为:
|
|
现在如果执行Test t = genTest()
这条语句的话,它会被编译器转化为:
|
|
RVO (Copy Elision)
C++ 11将Copy Elision优化加入C++标准中:
in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cv-unqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value
调用消耗:copy > move > RVO
浅拷贝和深拷贝
老生常谈的东西了,对于指针变量(或数组),必须执行按地址拷贝,这是默认生成的拷贝构造函数不能提供的。因此如果成员变量里有指针型或数组型变量,那么必须自己实现拷贝构造函数,用 memcpy
或 memcopy
进行按地址拷贝。
Move Constructor(C++ 11)
待总结…
参考资料
- Inside The C++ Object Model
- RVO V.S. std::move