1

重複の可能性:
この場合、コピー コンストラクターが呼び出されないのはなぜですか?

私は次のコードを持っています:

#include <iostream>
#include <new>

using namespace std;

class test {  
    int *p;  
public:
    test operator=(test a);
    test()  {
        p = new int [2];
        cout <<"Default Constructor was done here." << "\n";
    }

    test(const test &a) {
        p = new int [2];
        this->p[0] = a.p[0];
        this->p[1] = a.p[1];
        cout << "Copy Constructor was done here." << "\n";
    }

    ~test() {
        delete p;
        cout << "Destructor was done here." << "\n";
    }
    int set (int a, int b) {
        p[0] = a;
        p[1] = b;
        return 1;
    }

    int show () {
        cout << p[0] << " " << p[1] << "\n";
        return 2;
    }
};    

test test::operator=(test a) {
    p[0] = a.p[0]; 
    p[1] = a.p[1]; 
    cout << "Operator = was done here" << "\n";
    return *this;
}

test f(test x) {
    x.set(100, 100);
    return x;
}

int main () {
    test first;
    test second;
    first.set(12, 12);

    //f(first);
    //second = first;
    second = f(first);


    first.show();
    second.show();

    getchar ();
    return 0;
}

コピー コンストラクターは 3 回しか呼び出されませんでしたか? なんで?私が理解していれば、4 つのコピーを作成しました (オブジェクトを func に送信し、func は値を返し、オブジェクトを operator= に送信し、operator= は値を返します)。

4

1 に答える 1

3

これはおそらくコピー省略の影響です。コンパイラは、プログラムに影響を与えない限り、オブジェクトのコピーを自由に回避できます。この場合、コピー コンストラクター/デストラクターの副作用は、プログラムへの影響とは見なされません。一般に、関数パラメーターとして使用するために一時的なものをコピーすることは避けられます。一時的なものは後で破棄されるためです。

これは、標準の §12.8.32 にあります。

特定の基準が満たされると、オブジェクトのコピー/移動コンストラクタおよび/またはデストラクタに副作用がある場合でも、実装はクラス オブジェクトのコピー/移動構築を省略することができます。このような場合、実装は、省略されたコピー/移動操作のソースとターゲットを、同じオブジェクトを参照する 2 つの異なる方法として扱い、そのオブジェクトの破棄は、2 つのオブジェクトが削除された時点のいずれか遅い方の時点で発生します。最適化なしで破壊されました。copyelision と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます (複数のコピーを排除するために組み合わせることができます)。

  • クラスの戻り値の型を持つ関数の return ステートメントで、式が
    関数の戻り値の型と同じ cv 非修飾型の非揮発性自動オブジェクトの名前である場合、
    コピー/移動操作は、自動
    オブジェクトを関数の戻り値に直接
  • throw 式で、オペランドが非 volatile 自動オブジェクトの名前であり、そのスコープが最も内側の try ブロック (存在する場合) の末尾を超えない場合、オペランドからへのコピー/移動操作例外オブジェクト (15.1) は、自動オブジェクトを例外オブジェクトに直接構築することによって省略できます。
  • 参照 (12.2) にバインドされていない一時クラス オブジェクトが、同じ cv 非修飾型のクラス オブジェクトにコピー/移動される場合、一時オブジェクトを直接のターゲットに構築することにより、コピー/移動操作を省略できます。
    省略されたコピー/移動

  • 例外ハンドラーの例外宣言 (条項 15) が、例外オブジェクト (15.1)と同じ型 (cv 修飾を除く) のオブジェクトを宣言する場合、コピー/移動操作は
    、例外宣言をエイリアスとして扱うことによって省略できます。 exception-declaration
    によって宣言されたオブジェクトのコンストラクタとデストラクタの実行を除いて、プログラムの意味が変更されない場合は、例外オブジェクトに対して。

この場合、 によって返されたオブジェクトfを の入力として単純に使用する可能性operator=があります。これは、一時的なものであり、その後すぐに破棄されるためです。

于 2012-06-29T13:07:55.210 に答える