1

最近のインタビュープログラミングの課題で、C ++がどれほど錆びているかがわかったので、簡単なリンクリストを作成しました。私のリストでは、コピーの作成(そしてもちろん怠惰)を明示的に避けたかったので、プライベートコピーコンストラクターを宣言しました。リストの1つを所有する値でオブジェクトを返したいときに、問題が発生しました。

class Foo
{
   MyList<int> list;  // MyList has private copy constructor

   public:
      Foo() {};
};

class Bar
{
   public:
      Bar() {};

      Foo getFoo()
      {
         return Foo();
      }
};

Fooオブジェクトを値で返そうとすると、MyListにプライベートコピーコンストラクターがあるというコンパイラエラーが発生します。Return-Value-Optimizationは、コピーの必要性を否定する必要がありますか?コピーコンストラクターを作成する必要がありますか?この問題の解決策を探し始めるまで、移動コンストラクターについて聞いたことがありませんでしたが、それが最善の解決策ですか?もしそうなら、私はそれらを読む必要があります。そうでない場合、この問題を解決するための好ましい方法は何ですか?

4

3 に答える 3

5

標準では、コンストラクターが最適化されていない場合でも、コンストラクターにアクセスできる必要があることを明示的に示しています。12.8/32最近のドラフトを参照してください。

このような状況では、オブジェクトを移動可能でコピー不可にすることを好みます。これにより、所有権が非常に明確かつ明確になります。

それ以外の場合、ユーザーは常にshared_ptr. 共有所有権を非表示にすることは、せいぜい疑わしい考えです (すべての値が不変であることを保証できない限り)。

于 2012-06-26T14:16:59.137 に答える
3

基本的な問題は、値による戻りコピーされる可能性があることです。C ++の実装は、適用される場合にコピーの省略を適用するために標準で要求されていません。そのため、オブジェクトは引き続きコピー可能である必要があります。そのため、オブジェクトをいつ使用するかを実装が決定しても、コードが整形式であるかどうかには影響しません。

とにかく、それは必ずしもユーザーが望むかもしれないすべてのコピーに適用されるわけではありません。たとえば、コピー割り当ての省略はありません。

私はあなたの選択肢は次のとおりだと思います:

  • 適切なコピーを実装します。誰かがそれをコピーするために遅いプログラムで終わった場合、彼らのプロファイラーは彼らに言うでしょう、あなたが望まないのであればあなたは彼らを止めることをあなたの仕事にする必要はありません。
  • 適切な移動を実装しますが、コピーは実装しません(C ++ 11のみ)。
  • (または多分)パラメータgetFooを取るように変更し、オブジェクトをなんらかの方法で変更してコピーを回避します。そのためには効率的なものが役に立ちます。呼び出し元がを呼び出す前にaを作成する必要があるため、例のように実際にdefault-constructedを返す場合、これはかなり無意味です。Foo&Foo*swapgetFooFooFoogetFoo
  • Fooスマートポインタでラップされた動的に割り当てられたものを返します:auto_ptrまたはunique_ptr。オブジェクトを作成し、呼び出し元に唯一の所有権を譲渡するように定義された関数は、関数がないため、戻らないでくださいshared_ptrrelease()
  • コピーコンストラクターを提供しますが、これまでに使用したことがある場合は、なんらかの方法で爆発させます(リンクの失敗、中止、例外のスロー)。これに伴う問題は、(1)失敗する運命にあるが、コンパイラは何も言わない、(2)実装の品質を強制しているため、誰かが何らかの理由でRVOを故意に無効にした場合、クラスは機能しません。

私はいくつかを逃したかもしれません。

于 2012-06-26T15:17:07.090 に答える
2

MyList解決策は、他のメソッドを使用してコピー セマンティクスを実装する独自のコピー コンストラクターを実装することです。

...コピーを作成することを明示的に避けたかった

あなたは選ばなければなりません。のように、オブジェクトのコピーを作成することはできませんstd::istream。次に、そのようなオブジェクトをポインター/参照に保持する必要があります。これらはコピーできるためです (C++11 では、代わりに移動セマンティクスを使用できます)。または、コピーコンストラクターを実装します。これは、コピーが必要な各場所で問題を解決するよりもおそらく簡単です。

于 2012-06-26T14:22:57.397 に答える