对象的构造与析构
全局对象
C++保证在main函数之前将全局变量构造出来,在main函数结束后销毁
clang中会增加__cxx_global_var_init
调用构造函数,并且通过atexit
注册析构函数
1 | __cxx_global_var_init: # @__cxx_global_var_init |
多个全局对象在__cxx_global_var_init.1
(以此类推)中构造,每个文件有一个_GLOBAL__sub_I_
负责调用
1 | _GLOBAL__sub_I_example.cpp: # @_GLOBAL__sub_I_example.cpp |
局部静态对象
1 | void foo() { |
1 | foo(): # @foo() |
在函数中判断对应的guard variable
表示是否初始化,如果没有那么加锁__cxa_guard_acquire
然后调用对应的构造函数,注册析构函数
如果已经初始化直接跳转到.LBB0_3:
执行函数体内容
对象数组
1 | int main() { |
1 | lea rax, [rbp - 336] |
一个循环,调用构造函数,析构的时候同样是一个循环
new和delete
针对数组的new
不要出现下面的情况
1 | Base *b = new Derived[10]; |
For the first (non-array) form, expression must be a pointer to an object type or a class type contextually implicitly convertible to such pointer, and its value must be either null or pointer to a non-array object created by a new-expression, or a pointer to a base subobject of a non-array object created by a new-expression. The pointed-to type of expression must be similar to the type of the object (or of a base subobject). If expression is anything else, including if it is a pointer obtained by the array form of new-expression, the behavior is undefined.
For the second (array) form, expression must be a null pointer value or a pointer value previously obtained by an array form of new-expression whose allocation function was not a non-allocating form (i.e. overload (10)). The pointed-to type of expression must be similar to the element type of the array object. If expression is anything else, including if it’s a pointer obtained by the non-array form of new-expression, the behavior is undefined.
注意加粗的那句话,delete
关键词可以接受指向Base的指针,而delete[]
没有这句话
Important bug for C++ object dynam… | Apple Developer Forums
c++ - Possible bug on delete[] for all g++ versions or not defined behaviour for this? - Stack Overflow
operator delete, operator delete[] - cppreference.com
Placement Operator New
可以在指定位置构造一个对象
1 | Derived *d = static_cast<Derived *>(malloc(sizeof(Derived))); |
其实construct的实现就是用了这个
1 | template <class _Up, class... _Args> |
临时对象
sum = x + y
执行完成后就可以立即释放x + y
表达式所引入的临时变量。但是有两种情况是例外:
- 用临时变量来声明对象。例如
A sum = x + y
,表达式x + y
生成的临时对象实际成为了sum
,需要超出了sum
的作用域才能释放; - 将临时变量绑定到引用。例如
const A &sumRef = x + y
,如果立即释放x + y
所生成的临时对象,则引用类型的sumRef
则会失去意义;
当然还有左值引用之类的可以延长临时变量生命周期,这就不是这本书讨论的了