2017-03-09 6 views
0

これは、オーバーロードされた代入演算子と乗算演算子を含む比較的シンプルなコードです。私は両方の演算子の値によってオブジェクトを返しました。私が悩んでいるのは、代入演算子を使用すると、コピーコンストラクタは常に呼び出され、乗算演算子の場合、コピーコンストラクタは決して呼び出されないということです。ここで 異なる演算子の演算子オーバーロード中にコピーコンストラクタを呼び出す

#include<iostream> 
using namespace std; 
class foo { 
public: 
    int x; 
    foo() {x=1;} 
    foo(int a){x=a;} 
    foo(const foo &p){ 
    cout<<"CC:\tCopying from: "<<p.x<<'\t'<<&p<<"\tTo: "<<this<<endl; 
    } 
    foo operator=(const foo &r){ 
     cout<<"Assgn:\t"<<"Assigning from: "<<r.x<<'\t'<<&r 
      <<"\tTo: "<<this->x<<'\t'<<this<<endl; 
     return *this; 
    } 
    foo operator*(const foo &r){ 
     cout<<"Product:\t"<<"Multiplying from: "<<r.x<<'\t'<<&r 
      <<"\tTo: "<<this->x<<'\t'<<this<<endl; 
     return foo(x*r.x); 
    } 
}; 

int main() { 
    foo x(1),y(2); 
    foo z=x=y; 
    foo a=x*y; 
    x.x=1; y.x=2; 
    x*y*z; 
    x=y=z; 
    cout<<"X: "<<&x<<endl<<"Y: "<<&y<<endl<<"Z: "<<&z<<endl; 
} 

は出力です:基本的な事がある

Assgn: Assigning from: 2 0x7fff2cddbf70 To: 1 0x7fff2cddbf78 
CC: Copying from: 1 0x7fff2cddbf78 To: 0x7fff2cddbf68 
Product: Multiplying from: 2 0x7fff2cddbf70 To: 1 0x7fff2cddbf78 
Product: Multiplying from: 2 0x7fff2cddbf70 To: 1 0x7fff2cddbf78 
Product: Multiplying from: 7618584 0x7fff2cddbf68 To: 2 0x7fff2cddbf58 
Assgn: Assigning from: 7618584 0x7fff2cddbf68 To: 2 0x7fff2cddbf70 
CC: Copying from: 2 0x7fff2cddbf70 To: 0x7fff2cddbf48 
Assgn: Assigning from: 3 0x7fff2cddbf48 To: 1 0x7fff2cddbf78 
CC: Copying from: 1 0x7fff2cddbf78 To: 0x7fff2cddbf40 
X: 0x7fff2cddbf78 
Y: 0x7fff2cddbf70 
Z: 0x7fff2cddbf68 

、乗算演算子は、i「はfooのようなステートメントを持っていない場合でも(使用されたときにコピーコンストラクタが呼び出されないさん= X * y ')。しかし、 'a = b'の値を返す間に、コピーコンストラクタは、と呼ばれます。

私はコンパイラの最適化が出力にいくつかの変更を加えることを知っています。そのため、z = x = yz = x * yのような変数を宣言するとCCが呼び出されません。しかし、再びz = x * yのようにzを直接計算できるときにx = yを返すときにCCが呼び出されるのはなぜですか?これには特別な理由はありますか?同様に、代入演算子は異なる方法で扱われるか、代入演算子で*thisを返すので、一時変数を返す乗算演算子の場合とは異なります(これはASFAIKのためコンパイラが変数を区別できないためローカルおよびグローバルスコープの)。

答えて

0

答えに到達しようとしている間に私の前提の1つが間違っていました。

私は同じことを試みましたが、代入演算子の定義をちょうど少し変更して、最初にローカル変数に値を格納してから戻しました。この場合、コピーコンストラクタは呼び出されませんでした。

これは、コンパイラが異なるスコープの変数を区別できることを意味します。質問に投稿したコードは非ローカル変数を返すので、コピーコンストラクタが呼び出されます。

私は、クラス外の別の関数から代入演算子を呼び出すと、同じことが起こる(つまりCCが呼び出される)と推測しています。 CCが同じクラスの別のメンバ関数内から呼び出されたときに何が起こるかを見ることは面白いでしょう(おそらく同じでしょうが)。

関連する問題