4

次のコードを見て、将来問題が発生するかどうか、発生する場合は回避する方法を教えてください。

class Note
{
   int id;
   std::string text;

public:
   // ... some ctors here...

   Note(const Note& other) : id(other.id), text(other.text) {}

   void operator=(const Note& other) // returns void: no chaining wanted
   {
      if (&other == this) return;
      text = other.text;  
      // NB: id stays the same!    
   }
   ...
};

つまり、コピーコンストラクターで、(データベース)IDフィールドを含むオブジェクトの正確なコピーを作成する必要があります。一方、割り当てるときは、データフィールドをコピーするだけです。しかし、通常、copyctorとoperator=のセマンティクスは同じであるため、いくつかの懸念があります。

idフィールドは、Noteとその友人によってのみ使用されます。他のすべてのクライアントの場合、代入演算子は正確なコピーを作成します。ユースケース:メモを編集する場合は、copy ctorを使用してコピーを作成し、編集してから、メモを管理するNotebookクラスでsaveを呼び出します。

 Note n(notebook.getNote(id));
 n = editNote(n); // pass by const ref (for the case edit is canceled)
 notebook.saveNote(n);

一方、既存のメモと同じ内容で完全に新しいメモを作成したい場合は、次のように実行できます。

 Note n; 
 n = notebook.getNote(id); 
 n.setText("This is a copy");
 notebook.addNote(n);

このアプローチはもっともらしいですか?そうでない場合は、考えられる悪影響を指摘してください。どうもありがとう!

4

3 に答える 3

9

代入演算子から期待されるものと一致しないセマンティクスが必要な場合は、使用しないでください。代わりに、privateoperator=を宣言して無効にし、何が起こっているかを明確にする名前で関数を定義しますcopyDataFields

于 2010-02-05T19:52:34.087 に答える
4

これは特定のケースではうまくいくかもしれませんが、一般的にはお勧めしません。

STL などのライブラリは、コピー コンストラクターと代入演算子が「想定どおりに」動作することを期待しています。C++ のセマンティクスに違反すると、オブジェクトの STL コンテナーが正しく機能しないことがあります。STL は、コンテナーに応じて、さまざまな状況で、コピー コンストラクターと代入演算子の両方を呼び出します。

コードが思った通りに動かない場合、完全に混乱するのは非常に簡単です。

于 2010-02-05T21:05:49.697 に答える
1

技術的には実行可能であり、技術的には機能しますが、私はそのようにはしません。私が見る問題は次のとおりです。

  1. C++ 人口で知られている代入演算子の「自然な」セマンティックを変更します。

  2. コピー構築と代入という 2 つの双子の操作は、セマンティクスが異なるため一貫性がありません。

  3. 割り当てのように見えても、誤ってコピー コンストラクターを呼び出すのは簡単であるため、このソリューションはエラーが発生しやすくなります。プログラマーが 2 番目のユース ケースを次のように記述した場合:

    Note n = notebook.getNote(id);
    

    次に、割り当てではなくコピーコンストラクターが呼び出されるためn、予想とは異なるオブジェクトとして取得されます。

意図を明確かつ明示的にしないのはなぜですか。

Note& Notebook::editNote(int id);
Note  Notebook::createNote(int id);
于 2010-02-06T03:14:01.633 に答える