使用以下 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)。创建一个a
值为 1 的对象;
(2)。调用函数f()
。创建一个对象temp
,编译器发现该对象会被返回,所以直接在调用者的栈中创建;
(3)。通过调用;将f()
(ie, )temp
的返回对象赋值给 objecta
operator=()
a
(4)。对象使用相同的变量名作为参数(右值)a
传入。operator=()
a
(5)。该方法operator=()
在main::a
(左值,滥用符号)上调用,因此this
在函数中指向main::a
,[!!这是让我感到困惑的部分];
(6)。operator=()
改变main::a
toa
的值(即从 1 到 2);
(7)。编译器发现返回类型不是引用,并且*this
已经存在于 中main()
,所以只好*this
调用拷贝构造函数进行拷贝。但是,复制构造函数不会初始化对象,因此会创建一个未初始化的对象。
(8)。[!!不太确定这部分]左值和结果对象是同一个对象,因此由于优化,没有真正返回对象。
(9)。复制的对象被销毁,根据@Mike Seymour 的说法,创建这个对象是因为编译器不能省略它,因为构造函数和析构函数实际上都做了一些事情(例如输出值和地址)。
(10)。退出时operator=()
,对象a
被销毁。
(11)。退出时main()
,对象main::a
最终被销毁。
以上解释了输出,但是,我目前的理解可能不正确。如果我错了,请帮助我理解这一点。非常感谢。