3

私はこの割り当てがC++でどのように機能するかを理解しようとしました:

Test other = toto();

これは完全なコードソースです:

#include <iostream>

class Test
{
public:
    Test()
    {
        j = i++;
        std::cout<<"default constructor "<<j<<std::endl;
    }

    Test(const Test&)
    {
        std::cout<<"constuctor by copy "<<j<<std::endl;
    }
    Test & operator=(const Test&)
    {
        std::cout<<"operator = "<<j<<std::endl;
        return *this;
    }
    int j;
    static int i;
};

int Test::i = 0;

Test toto()
{
    Test t;
    return t;
}

int main()
{
    Test other = toto();
    std::cout<<other.j<<std::endl;
    Test another;
    return 0;
}

コピーまたは演算子=によってコンストラクターを使用していないコードなので、実際にどのように機能するのかわかりません...gcc4.7.0を使用しました

あなたの助けのためにThranks:)

ジェローム

4

2 に答える 2

7

次のフォーマットセマンティクス:

Test other = toto();

複数のコピーが含まれます(ただし、割り当ては含まれません)。ただし、コンパイラーはすべての異なるインスタンスを削除することができます。これにより、コピーが削除されます。ほとんどすべてのコンパイラがこの最適化を行います。

より具体的には、標準ではクラス型の値が返される場所を指定していませんが、通常の解決策は、呼び出し元がスペースを割り当て、そのスペースへの非表示のポインターを関数に渡すことです。上記の最適化なし:

Test
toto()
{
    Test t;
    return t;
}

その結果、ローカル変数tが作成され、returnステートメントがt非表示のポインターが指すスペースにコピーされます。ここでの最適化(名前付き戻り値最適化、またはNRVOと呼ばれる)により、コンパイラーは、ローカルでt個別に作成するのではなく、の非表示ポインターが指すスペースを使用します。t(明らかに、これを行うと、コピー後にそうでない場合のように、破壊されません。)t

宣言では:

Test t = toto();

、正式なセマンティクスでは、コンパイラーがTest型の一時スペースにスペースを割り当て、このスペースのアドレスを隠しポインターとしてに渡し、totoこの一時スペースをにコピ​​ーしtて破棄します。ここでの最適化は、コンパイラがのアドレスを t直接にtoto渡し、中間の一時的なものを排除することで構成されます。

于 2012-05-11T12:41:27.160 に答える
3

コンストラクター呼び出しを回避するための一般的な最適化である戻り値の最適化を見てください。

于 2012-05-11T12:35:46.357 に答える