析构函数和拷贝构造函数调用。(为什么它被调用在这些时间)
我有以下代码析构函数和拷贝构造函数调用。(为什么它被调用在这些时间)
#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;
在打印(b)
后调用复制构造函数并生成Copy-construct(1)
。
而且之后的(c)
打印拷贝构造函数被再次调用两次?我不是一定的此功能的工作原理来产生 Object func(Object var) { return var; }
和只是Destruct(1)
之后被调用(d)
在打印之前的两倍。
对于长期的问题感到抱歉,我很困惑以上。
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)
复制构造函数在这里被调用,因为Object 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或复制结构)被弹出堆栈和析构函数被调用用于每个。
至于第一个问题,Object v4 = v1;
是Object v4(v1);
的语法糖,它更明显地调用了拷贝构造函数。
第二个有点复杂。当按值传递变量给函数时,它们必须被复制 - 从而调用拷贝构造函数。对象的副本也必须放置在调用方可以访问的位置的堆栈上,因为当函数返回时传递给该函数的副本不再存在。在完成这两个副本之后,该参数在从堆栈弹出时被破坏,并且由于未使用该值而导致返回值被破坏。他们有相同的ID,因为他们是v1
的副本。
我有这个问题,首先是 为什么Object v4 = v1; (b)的打印 之后复制构造(1)调用副本 构造函数并产生 副本构造(1)。
尽管=
符号,您在这里调用复制构造函数。请记住,你没有默认的构造函数。您正在构建新的Object
并将其初始化为值v1
。是你做的事:
cout << "(b)" << endl;
Object v4(0);
v4 = v1;
...你会看到...
(b)
Construct(0)
0 = 1
...我想你期待。
而且(三) 拷贝构造函数又被称为印刷后 两次?我不是一定这样 功能如何运作,以产生对象 FUNC(对象VAR){VAR回报; }
在这里,你是由值传递var
(而不是通过引用[&]),这意味着该对象的副本被创建(一个呼叫到拷贝构造)。然后你返回另一个对象 (再次,而不是引用),所以必须做另一个副本(第二次调用复制构造函数)。
和只是自毁(1)得到 (d)在打印之前调用两次之后。
那些刚刚使用复制构造函数创建的对象?他们只是超出了范围,他们的析构函数被调用了。
当你delete
v5
它的析构函数被调用。
然后你到达main
功能的结束和你堆栈(v1
,v2
,v4
)上创建三个Object
情况下达到其寿命结束和堆栈展开销毁。
您可能已经注意到,您具有与构造函数调用一样多的析构函数调用!
ahk非常感谢。还有一个问题,'Destruct(1)'的最后3个输出是由于Object v1(1),v2 = v1,Object v4 = v1;'correct?和'Destruct(5)'是在之前被人为删除的? – silent 2010-06-06 07:20:01