0

このコードでは、リターン時に巨大なベクトルを(コンパイラーによっては)コピーすることができます。

vector<string> foo() {
  vector<string> vec;
  //make vec huge
  return vec;
}
vector<string> bar = foo();

コンパイラの最適化に依存せずに、ベクトルのコピーを回避するにはどうすればよいですか?

ここで、これは1つのreturnステートメントを使用した単純な例であることを理解してください。しかし、より複雑なケースでは、優れたコンパイラーでさえ、ベクトルのコピーを回避するための最適化を実行できない可能性があります。(別の質問に対するこの回答は、そのようなケースの1つに言及しています。)

(コンパイラーの最適化に依存することは、そもそも私にはかなり奇妙に思えました。なぜなら、これとそのコンパイラーが内部でどのように動作するかを心配するのではなく、優れた移植性のあるC++コードを書くことになっているからです。したがって、「コンパイラの最適化」は他の質問に答えるので、私は困惑します。)

私がこれまでに思いついたアイデアの1つは、C++11のスマートポインターを使用することです。

shared_ptr<vector<string>> foo() {
  shared_ptr<vector<string>> vec_ptr = make_shared<vector<string>>();
  //make *vec_ptr (i.e. the actual vector) huge
  return vec_ptr;
}
shared_ptr<vector<string>> bar_ptr = foo();
//now, *bar_ptr is the underlying vector we can use

これにより、すべての場合にコピーが回避されるようです。問題は、このコードが非常に面倒になっていることです。

面倒ではない良い代替案はありますか?おそらく、C ++ 11は、右辺値参照を通じていくつかの新しい「移動」機能を提供します。それらは助けてもらえますか?

4

2 に答える 2

3

おそらく、C ++ 11は、右辺値参照を通じていくつかの新しい「移動」機能を提供します。それらは助けてもらえますか?

はい、コンパイラが何らかの理由でRVOを使用しない場合、std :: vectorにはムーブ演算子があり、このような単一の変数を返すときに適用できるため、この場合はムーブを使用します。元のコードは、c ++ 11コンパイラを使用してコンパイラを変更せずに、これを実行する必要があります。

于 2012-12-04T13:42:30.077 に答える
0

古い学校のオプションの1つは、関数への参照としてベクトルを渡し、必要に応じて変更を加えることです。

void foo(vector<string> &vec){
...

foo(bar);

一方、セマンティクスを移動すると、希望どおりに動作するはずです。コードを変更しなくても発生する可能性があります。デバッガーを使用して確認できます。さらに詳しく説明します。

編集:この質問は、元のコードが自動的に移動操作として機能する必要があることを示しているようです。 この投稿にはもっと多くの情報があるようですが、私は少し眠くてすべてを把握することができません。

于 2012-12-04T13:28:37.403 に答える