5

View と、View がその Shape オブジェクトを「所有」する Shape クラスがあります。これをunique_ptrのベクトルとして実装しています。関数 View::add_shape(std::unique_ptr&& shape) では、rvalue パラメーターで std::move を使用してコンパイルする必要があります。なんで?(GCC 4.8 を使用)

#include <memory>
#include <vector>
using namespace std;

class Shape { };
class View
{
  vector<unique_ptr<Shape>> m_shapes;
  public:
  void add_shape(unique_ptr<Shape>&& shape)
  { 
    m_shapes.push_back(std::move(shape));// won't compile without the std::move
  }
};


int main()
{
  unique_ptr<Shape> ups(new Shape);
  View v;
  v.add_shape(std::move(ups));
}
4

2 に答える 2

7

はい、パラメーターからの右辺値参照は、呼び出し元の観点から関数を選択するためにのみ使用され、関数内の左辺値参照のように動作します。

その理由は、値を移動できるのは 1 回だけであり、パラメーターの右辺値を自動的に保持するのは危険すぎると見なされたためです。パラメーターの型は、この関数が右辺値を受け入れ、実際に値を移動する実装を提供することでこれを潜在的に利用することを示します。メソッドのこのバージョンをオーバーロードすることにより、移動しないバージョンを優先して使用できます。または、単に関数が右辺値を必要とすることを示しています。

関数の実装で何が起こるかは別のことです。次のような方法を検討してください

void add_shape_twice(unique_ptr<Shape>&& shape)
{ 
  m_shapes.push_back(shape);
  m_shapes.push_back(shape);
}

パラメーターとして右辺値参照のままである場合shape: 誤って値を 2 回移動したことになります。実際の関数はより長くなる可能性があり、パラメーターを複数回 (明示的に、またはループまたはパック展開内で) 参照することは非常に一般的であるため、エラーが発生する可能性は非常に高くなります。

たとえ私たち全員がそれを認識していて、それを決して忘れなかったとしても、それはまた、右辺値性を捨てる必要があることを意味し、これはコードを非常にぎこちなくします。右辺値性を常に追加および削除します。

于 2013-09-28T07:14:57.220 に答える