#include <iostream>
class A
{
public:
A(int n = 0) : m_n(n) { }
A(const A &a) : m_n(a.m_n) { ++m_copy_ctor_calls; }
~A() { ++m_dtor_calls; }
private:
int m_n;
public:
static int m_copy_ctor_calls;
static int m_dtor_calls;
};
int A::m_copy_ctor_calls = 0;
int A::m_dtor_calls = 0;
int main()
{
A *p = nullptr;
{
const A a = 2;
p = new A[3];
p[0] = a;
}
std::cout << A::m_copy_ctor_calls << A::m_dtor_calls;
p[1] = A(1);
p[2] = 2;
delete [] p;
std::cout << A::m_copy_ctor_calls << A::m_dtor_calls << std::endl;
return 0;
}
答案: 0106
1. 同上一题,注意initialization和assignment的区别。
可以这样理解,当initialization时候,A a 的对象a 是不完整的,没法调用 = operator 所以 A a = 2 是调用的构造函数,具体是copy构造函数还是带参数的构造函数还是默认构 造函数,取决于等号右边是什么,如果是对象,则是copy构造函数,如果是int,则查看带int的构造函数。
注意 p[2] = 2; 这个和 A a = 2是有区别的,前者是p[2]已经是一个完整的对象,可以调用=operator,所以调用A(int)将2转成一个临时对象,然后p[2]调用 = operator完成赋 值。 而 A a = 2时 a是不完整的,需要的是构造函数,按前面说的寻找对应的构造函数。
2. 注意scope结束过后应有的对象销毁。
3. 注意右值在expression结束过后就销毁,不要忘记这时候他们调用了析构函数。
4. 注意p[0] = a,是copy a 的值到heap 中 p的位置。 所以即使scope结束,a调用析构,只是a在stack中的内存被释放,但是不会影响他在heap中的copy,所以这里加上右值一 共有6次析构调用,