1

私の知る限り、次の場合にコピー コンストラクターを呼び出します。
1 オブジェクトをインスタンス化し、別のオブジェクトの値で初期化する場合
2 オブジェクトを値渡しする場合。
3 オブジェクトが関数から値によって返される場合。
私はこれをテストすることに決め、これをテストするこの小さなプログラムを作成しました (コンストラクターが呼び出されるたびにメッセージを表示します。最初の 2 つのケースでは機能するようですが、3 番目のケースでは機能しないようです。間違いを見つけたいです) . アイデアは大歓迎です。

#include <iostream>

using namespace std;

class Circle{
private:
    double* data;
public:
    Circle();
    Circle(double* set);
    Circle(const Circle& tt1);
    ~Circle();
    Circle& operator=(const Circle& tt1);
};



Circle :: Circle()
{
    cout << "Default constructor called" << endl;
    data = NULL;
}

Circle :: Circle(double* set)
{
    cout << "Set up constructor called" << endl;
    data = new double[3];
    copy(set, set+3, data);
}

Circle :: Circle(const Circle& tt1)
{
    cout << "Copy constructor called" << endl;
    data = new double[3];
    copy(tt1.data, tt1.data+3, this->data);
}
Circle :: ~Circle()
{
    cout << "Destructor called!" << endl;
    delete[] data;
}

Circle& Circle :: operator=(const Circle& tt1)
{
    cout << "Overloaded = called" << endl;
    if(this != &tt1)
    {
        delete[] this->data;
        this->data  = new double[3];
        copy(tt1.data, tt1.data+3, this->data);
    }
    return *this;
}

void test2(Circle a)
{

}
Circle test3()
{
    double arr [] = { 3, 5, 8, 2};
    Circle asd(arr);
    cout<< "end of test 3 function" << endl;
    return asd;
}

int main()
{
    cout <<"-------------Test for initialization" << endl;
    double arr [] = { 16, 2, 7};
   Circle z(arr);
    Circle y = z;
   cout << "-------------Test for pass by value" << endl;
   test2(z);
   cout <<"------------- Test for return value-------"<<endl;
   Circle work = test3();

    cout<< "-----------Relese allocated data" << endl;
    return 0;
}
4

2 に答える 2

8

戻り値の最適化により、3 番目のテスト ケースのコピー コンストラクター呼び出しは、コンパイラーによって最適化されなくなります。

于 2013-05-30T19:19:00.660 に答える
3

ほとんどの場合、コンパイラがコードの意味を変更することは許可されていません。コードの観察可能な動作を変更することなく、コードを記述したものからより最適なものに劇的に変更できます (最適化する場合も同様です)。

これが、デバッグ時に、生成されたコードが、観察可能な状態をそのまま維持しながら、記述したものとはまったく異なることを行うため、多くの紛らわしいことが表示される理由です。これは実際にデバッガーの作成を困難にします。たとえば、デバッグ中に変数の値を調べたい場合、コンパイラーは変数が存在する必要さえないと判断した可能性があり、その場合、デバッガーは何を表示する必要がありますか?

非常に少数のケースでは、コンパイラがコードの意味を変更することが許可されています。RVOと NRVO [上記と同じリンク] は、これらの 2 つの例です。コンパイラは、これらの限られたケースでコピー コンストラクターを省略できます。これが表示されているものです。コンパイラは、コピー コンストラクターが存在し、アクセス可能であることを引き続き確認する必要があります (たとえば、プライベートではない、削除されている、または生成できないなど) が、使用することはできません。

このため、コピー コンストラクター [および推論デストラクタによる] は通常のことを行う必要があります。省略されているかのように、明らかに異なる動作が得られます。

于 2013-05-30T19:53:56.917 に答える