繁体   English   中英

析构函数和复制构造函数调用..(为什么在这些时候被调用)

[英]destructor and copy-constructor calling..(why does it get called at these times)

我有以下代码

#include <iostream>
using namespace std;

class Object {

public:
   Object(int id){
     cout << "Construct(" << id << ")" << endl; 
     m_id = id;       
   }

   Object(const Object& obj){
      cout << "Copy-construct(" << obj.m_id << ")" << endl;  
      m_id = obj.m_id;
   }

   Object& operator=(const Object& obj){
      cout << m_id << " = " << obj.m_id << endl; 
      m_id = obj.m_id;
      return *this; 
   }

   ~Object(){
       cout << "Destruct(" << m_id << ")" << endl; 
   }
private:
   int m_id;

};

Object func(Object var) { return var; }

int main(){
   Object v1(1);
   cout << "( a )" << endl;
   Object v2(2);
   v2 = v1;
   cout << "( b )" << endl;
   Object v4 = v1;
   Object *pv5;
   pv5 = &v1;
   pv5 = new Object(5);
   cout << "( c )" << endl;
   func(v1);
   cout << "( d )" << endl;
   delete pv5;
}

哪个输出

Construct(1)
( a )
Construct(2)
2 = 1
( b )
Copy-construct(1)
Construct(5)
( c )
Copy-construct(1)
Copy-construct(1)
Destruct(1)
Destruct(1)
( d )
Destruct(5)
Destruct(1)
Destruct(1)
Destruct(1)

我对此有一些疑问,首先是为什么Object v4 = v1; 调用copy构造函数,并在( b )打印后生成Copy-construct(1) ( b )

同样在打印( c ) ,复制构造函数再次被调用两次?,我不确定该函数如何产生该Object func(Object var) { return var; } Object func(Object var) { return var; }

并且在输出( d )之前,两次调用Destruct(1)之后。

很长的问题很抱歉,我对以上情况感到困惑。

Object v1(1);
// Construct(1)

常规构造函数调用自动堆栈变量(在函数末尾销毁)。

cout << "( a )" << endl;
// ( a )

Object v2(2);
// Construct(2)

另一个构造函数调用。

v2 = v1;
// 2 = 1

之所以调用赋值运算符,是因为已经创建了v2(我们将其称为构造函数),现在我们将一个现有对象分配给另一个。

cout << "( b )" << endl;
// ( b )

Object v4 = v1;
// Copy-construct(1)

之所以在这里调用复制构造函数,是因为仍未创建对象v4,因此我们将其创建为v1的副本。 这里的赋值与您执行Object v4(v1)含义相同

Object *pv5;
pv5 = &v1;
pv5 = new Object(5);
// Construct(5)

调用堆对象的构造函数(使用delete显式销毁)。

cout << "( c )" << endl;
// ( c )

func(v1);
// Copy-construct(1) <br />
// Copy-construct(1) <br />
// Destruct(1) <br />
// Destruct(1) <br />

首先调用复制构造函数将v1复制到参数var。 再次调用它以创建var的副本作为返回给调用方的值。 退出函数时,var从堆栈中弹出时被破坏。 返回值在表达式func(v1)之后销毁。

cout << "( d )" << endl;
// ( d )

delete pv5;
// Destruct(5)

pv5指向的对象被手动销毁。

} // end of main
// Destruct(1) <br />
// Destruct(1) <br />
// Destruct(1) <br />

自动变量v1,v2,v4(均已从赋值或复制构造复制了v1的ID)从堆栈中弹出,并为每个变量调用析构函数。

我对此有一些疑问,首先是为什么对象v4 = v1? 在打印(b)之后,调用copy构造函数并产生Copy-construct(1)。

尽管有=符号,您仍在此处调用复制构造函数。 请记住,您没有默认的构造函数。 您正在构造一个新的Object ,并使用v1的值对其进行初始化。 您要做的是:

cout << "( b )" << endl;
Object v4(0);
v4 = v1;

...你会看到...

( b )
Construct(0)
0 = 1

...我想你在期待。

同样在打印(c)之后,复制构造函数再次被调用两次?,我不确定该函数如何产生该对象。func(Object var){return var; }

在这里,您按值(而不是引用[&])传递var ,这意味着将创建对象的副本(对副本构造函数的一次调用)。 然后,您返回另一个对象(再次,而不是引用),因此必须进行另一个复制(对复制构造函数的第二次调用)。

并且在输出(d)之前,两次调用Destruct(1)之后。

您刚刚使用复制构造函数创建的那些对象? 他们只是超出范围,并调用了其析构函数。

delete v5时, delete调用其析构函数。

然后,您到达main函数的末尾,并且在堆栈上创建的三个Object实例( v1v2v4 )到达其生命周期的尽头,并在取消堆栈堆栈时被销毁。

您可能已经注意到,与构造函数调用一样,您拥有完全相同的析构函数调用!

关于第一个问题, Object v4 = v1; Object v4(v1);语法糖Object v4(v1); ,显然可以调用复制构造函数。

第二个比较复杂。 将变量按值传递给函数时,必须将其复制-从而调用复制构造函数。 还必须将对象的副本放在调用者可以访问它的位置的堆栈上,因为当函数返回时,传递给函数的副本将不复存在。 制作完这两个副本之后,将参数从堆栈中弹出时将其销毁,并且由于未使用其值,因此销毁了返回值。 它们具有相同的ID,因为它们是v1副本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM