次の 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()
(つまり、temp
) を objecta
にoperator=()
割り当てa
ます。
(4)。オブジェクトは、同じ変数名を使用してパラメーター (右辺値) としてa
渡されます。operator=()
a
(5)。メソッドoperator=()
はmain::a
(左辺値、表記の乱用) で呼び出されるため、関数内で [!!これは私を混乱させた部分]; をthis
指します。main::a
(6)。の値をtoのoperator=()
値に変更します (つまり、1 から 2 に)。main::a
a
(7)。コンパイラは、戻り値の型が参照ではなく、*this
既に に存在するmain()
ことを検出したため*this
、コピー コンストラクターを呼び出してコピーする必要があります。ただし、コピー コンストラクターはオブジェクトを初期化しないため、初期化されていないオブジェクトが作成されます。
(8). [!!この部分についてはよくわかりません] 左辺値と結果のオブジェクトは同じオブジェクトであるため、最適化のために実際にはオブジェクトは返されません。
(9)。@Mike Seymourによると、コピーされたオブジェクトは破棄されます。このオブジェクトは、コンストラクターとデストラクターの両方が実際に何かを行うため(値とアドレスを出力するなど)、コンパイラーがそれを省略できないため作成されます。
(10)。を終了するoperator=()
と、オブジェクトa
は破棄されます。
(11)。を終了するmain()
と、オブジェクトmain::a
は最終的に破棄されます。
上記は出力を説明していますが、私の現在の理解は正しくない可能性があります。私が間違っている場合は、これを理解するのを手伝ってください。どうもありがとう。