2

私は次の機能を持っています:

void read_int(std::vector<int> &myVector)

これにより、参照を埋めることができますmyVector。次のように使用されます。

std::vector<int> myVector;
read_int(myVector);

コードを少しリファクタリングして(元の機能を維持して)最終的にこれを実現したい:

auto myVector = read_int();   // auto is std::vector<int> 

これを達成するための最良の中間関数は何でしょうか?


次の率直な答えは最適ではないように思えます。

std::vector<int> read_int() {
    std::vector<int> myVector_temp;
    read_int(myVector_temp);
    return myVector_temp;
}
4

2 に答える 2

3

明白な答えは正しく、基本的に最適です。

void do_stufF(std::vector<int>& on_this);    // (1)
std::vector<int> do_stuff_better() {         // (2)
    std::vector<int> myVector_temp;          // (3)
    do_stuff(myVector_temp);                 // (4)
    return myVector_temp;                    // (5)
}

(3)では、自動ストレージ (スタック上) に名前付きの戻り値を作成します。

(5)では、関数から名前付きの戻り値のみを返し、その名前付きの戻り値以外を関数内の他の場所で返すことはありません。

(3)(5)のおかげで、コンパイラはmyVector_tempオブジェクトの存在を除外することができます (おそらくそうするでしょう) 。関数の戻り値を直接構築し、それを呼び出します myVector_temp。既存の移動コンストラクターまたはコピー コンストラクターが必要ですが、それは呼び出されません。

一方、 を呼び出すときdo_stuff_better、一部のコンパイラは呼び出し時に割り当てを省略することもできます。

std::vector<int> bob = do_stuff_better();     // (6)

コンパイラは、「bob へのポインター」を効果的に渡し、do_stuff_better()その戻り値をbobの場所に構築するように指示し、このコピー構築も省略できます (構築するようにdo_stuff_better()要求された場所が呼び出されるように、呼び出しがどのように発生するかを調整できます)。の戻り値は の場所と同じですbob)。

また、C++11 では、両方の elision の要件が満たされていない場合、またはコンパイラがそれらを使用しないことを選択した場合でも、どちらの場合も a のmove代わりに a を実行する必要がありますcopy

(5)では、ローカルで宣言された自動保存期間変数をプレーンでシンプルなreturnステートメントで返しています。moveこれにより、省略されていない場合は戻り値が暗黙になります。

(6)で、関数は右辺値である名前のないオブジェクトを返します。bobそれから を構築する場合は、構築しmoveます。

moveing astd::vectorは、〜3つのポインターの値をコピーしてから、その大きさに関係なくソースをゼロにすることで構成されvectorます。要素をコピーまたは移動する必要はありません。

内の名前付きローカル変数を削除し、 の値do_stuff_better()を削除して代わりに を直接構築する上記の両方の省略は、いくぶん脆弱です。コンパイラがこれらの省略を実行できるルールと、コンパイラが実際に省略を実行する状況を学ぶことは価値があります。returndo_stuff_better()bob

壊れやすい例として、エラー状態を確認した後return std::vector<int>()に inを実行したブランチがある場合do_stuff_better()、関数内の省略はおそらくブロックされます。

省略がブロックされていたり、コンパイラがそれを実装していない場合でも、コンテナーが実行されるという事実はmove、実行時間のコストが最小限になることを意味します。

于 2013-07-31T19:40:22.047 に答える
1

ムーブセマンティクスについてもっと読む必要があると思います(Googleクエリへのリンク、これに関する論文はたくさんあります-1つだけ選んでください)。

つまり、C++ では、すべての STL コンテナーは、関数からそれらを返すと、それらの内容が戻り値 (いわゆる右参照) から割り当て先の変数に移動されるように記述されています。実際には、データの代わりに std::vector のいくつかのフィールドのみをコピーします。その内容をコピーするよりもはるかに高速です。

于 2013-07-31T15:41:48.033 に答える