用下面的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