3

list< vector<char> >たとえば、使用などのSTLコンテナを初期化すると、my_list.push_back(vector<char>(5000, 'T'))これは構築後にコピーされますか? それとも、コンパイラーはlist< vector<char> >自身の内部でコンストラクターを呼び出しますか?

4

2 に答える 2

7

C++03 ではpush_backとして定義されていvoid push_back(const T& x);ます。つまり、 を構築してvectorおり、そのようなテンポラルへの const 参照が に渡されていることを意味しますlist。次に、そのlistような要素のコピーを格納するために、コピー コンストラクターを内部的に呼び出します。

void push_back(T&& x);C++11 には、 temporal への右辺値参照を取得するための追加の定義があり、vectorその結果、move コンストラクターが内部で呼び出されて、によって保持されているコピーが初期化されますlist

于 2011-09-29T19:56:02.647 に答える
0

コンパイラは賢いです。本当に賢い。この場合、「コピー省略」と呼ばれる最適化があります。C++ 標準では、一時オブジェクトを使用して同じ型のオブジェクトを初期化し、そのオブジェクトのコピー コンストラクターに副作用がない場合、コンパイラはコピーを省略できます。

これは、より一般的な "as if" ルールと同じクラスの最適化です。このルールにより、結果として得られるプログラムの観察可能な動作が、標準に正確に従っているかのように「あたかも」同じである限り、コンパイラーはほぼすべての処理を実行できます。

これがプログラムの例です。-O0 と -O3 の両方を指定した gcc 4.4.5 では、このコードは "1" を出力します。ここでGCCが間違っていると思います...一部のコンパイラは、コピーが行われたことを示す「2」を出力します。これは、検出できないはずの動作を検出しようとする際にトリッキーになるところです。これらのコンパイラの 1 つで、それを知る唯一の方法は、結果のアセンブリに飛び込むことです。

#include <iostream>

struct elision
{
    explicit elision(int i) : v(i) {
    }

    elision(elision const &copy) : v(copy.v+1) {
    }

    int v;
};

int main()
{
    elision e(elision(1));
    std::cout << e.v << std::endl;
    return 0;
}
于 2011-10-01T01:03:58.733 に答える