对copy-constructor和析构函数的无关调用

Laz*_*zer 2 c++ destructor copy-constructor

[跟进这个问题 ]

class A
{
    public:
         A()          {cout<<"A Construction"     <<endl;}
         A(A const& a){cout<<"A Copy Construction"<<endl;}
        ~A()          {cout<<"A Destruction"      <<endl;}
};

int main() {
    {
        vector<A> t;
        t.push_back(A());
        t.push_back(A());   // once more
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

A Construction        // 1
A Copy Construction   // 1
A Destruction         // 1
A Construction        // 2
A Copy Construction   // 2
A Copy Construction   // WHY THIS?
A Destruction         // 2
A Destruction         // deleting element from t
A Destruction         // deleting element from t
A Destruction         // WHY THIS?
Run Code Online (Sandbox Code Playgroud)

ken*_*ytm 16

为了清楚地看到发生了什么,我建议this在输出中包含指针以识别哪个A正在调用该方法.

     A()          {cout<<"A (" << this << ") Construction"     <<endl;}
     A(A const& a){cout<<"A (" << &a << "->" << this << ") Copy Construction"<<endl;}
    ~A()          {cout<<"A (" << this << ") Destruction"      <<endl;}
Run Code Online (Sandbox Code Playgroud)

我得到的输出是

A (0xbffff8cf) Construction
A (0xbffff8cf->0x100160) Copy Construction
A (0xbffff8cf) Destruction
A (0xbffff8ce) Construction
A (0x100160->0x100170) Copy Construction
A (0xbffff8ce->0x100171) Copy Construction
A (0x100160) Destruction
A (0xbffff8ce) Destruction
A (0x100170) Destruction
A (0x100171) Destruction
Run Code Online (Sandbox Code Playgroud)

所以流程可以解释为:

  1. 创建临时A(... cf).
  2. 临时A(... cf)被复制到向量(... 60)中.
  3. 临时A(... cf)被销毁.
  4. 创建了另一个临时A(... ce).
  5. 向量展开,该向量中的旧A(... 60)被复制到新位置(... 70)
  6. 另一个临时A(... ce)被复制到向量(... 71)中.
  7. 所有不必要的A(...... 60,...... ce)副本现在都被销毁了.
  8. 矢量被破坏,因此内部的A(... 70,... 71)也被破坏.

如果你这样做,第5步将会消失

    vector<A> t;
    t.reserve(2); // <-- reserve space for 2 items.
    t.push_back(A());
    t.push_back(A());
Run Code Online (Sandbox Code Playgroud)

输出将变为:

A (0xbffff8cf) Construction
A (0xbffff8cf->0x100160) Copy Construction
A (0xbffff8cf) Destruction
A (0xbffff8ce) Construction
A (0xbffff8ce->0x100161) Copy Construction
A (0xbffff8ce) Destruction
A (0x100160) Destruction
A (0x100161) Destruction
Run Code Online (Sandbox Code Playgroud)