用下面的C++程序:奇怪的拷贝构造函数
#include <memory>
#include <iostream>
using namespace std;
struct my_class{
int value;
my_class(int id): value(id){
cout<<"constructing "<<id<<endl;
cout<<"address is "<<static_cast<const void *>(this)<<endl;
}
my_class(const my_class & a){
cout<<"construct copying "<<a.value<<endl;
cout<<static_cast<const void *>(this)<<"<-"<<static_cast<const void *>(&a)<<endl;
}
my_class operator=(const my_class & a){
cout<<"assignment copying "<<a.value<<endl;
this->value = a.value;
cout<<static_cast<const void *>(this)<<"<-"<<static_cast<const void *>(&a)<<endl;
return *this;
}
~my_class(){
cout<<"deleting "<<this->value<<endl;
cout<<"address is "<<static_cast<const void *>(this)<<endl;
}
};
my_class f(){
cout<<"==in f=="<<endl;
my_class temp(2);
cout<<"==out f=="<<endl;
return temp;
}
int main(){
cout<<"==in main=="<<endl;
my_class a(1);
a = f();
a.value++;
cout<<"==out main=="<<endl;
return 0;
}
我得到了以下结果:
====
==in main==
constructing 1
address is 0x28ff04
==in f==
constructing 2
address is 0x28ff0c
==out f==
assignment copying 2
0x28ff04<-0x28ff0c
construct copying 2
0x28ff08<-0x28ff04
deleting 2686868
address is 0x28ff08
deleting 2
address is 0x28ff0c
==out main==
deleting 3
address is 0x28ff04
===
谁能向我解释与地址“0x28ff08”的对象会发生什么和从地址“0x28ff04”的对象构造相关副本?我真的不明白为什么复制构造函数在这里被调用。
我不知道如果我得到这个正确的,因此我想进一步详细解释它。任何人都会发现我的错误,请指出。
首先,图像示出执行流的详细信息:
(1)。创建一个值为1的对象a
;
(2)。呼叫功能f()
。创建一个对象temp
,编译器发现该对象将被返回,所以它直接在调用者的堆栈中创建;
(3)。通过调用a
的operator=()
将返回的对象f()
(即,temp
)分配给对象a
;
(4)。对象a
作为参数(rvalue)使用相同的变量名称a
传入operator=()
。
(5)。方法operator=()
被调用main::a
(左值,与滥用符号),因此this
在函数指向main::a
,[!!这是困惑我的部分];
(6)。 operator=()
将main::a
的值改变为a
的值(即从1到2);
(7)。编译器发现返回类型不是引用,并且main()
中已存在*this
,因此它必须通过调用复制构造函数复制*this
。但是,复制构造函数不会初始化该对象,因此会创建一个未初始化的对象。
(8)。 [!!对此部分不太确定]左值和生成的对象是同一个对象,因此没有对象因优化而返回。
(9)。根据@Mike Seymour的说法,被复制的对象被销毁,因为编译器不能忽略它,因为构造器和析构器都会做某些事情(例如输出值和地址)。
(10)。当退出operator=()
时,对象a
被销毁。
(11)。当退出main()
时,对象main::a
最终被销毁。
上面解释了输出,但是,我目前的理解可能不正确。如果我错了,请帮助我理解这一点。非常感谢。
您的输出与代码中的日志记录不匹配。 – Useless
此代码具有未定义的行为,因为当通过复制构造函数创建对象时,您正在使用'value'而不初始化它。 –
复制构造函数创建的对象从不使用。正如你所看到的,只要程序离开复制分配,对象就会被销毁。顺便说一句,我没有提供默认构造函数,为什么可以在不初始化的情况下创建对象。 – RainSia