1

何よりもまず、皆さんを私の考えのハイウェイに連れて行きましょう(簡単に言えば、私はこれらのことを想像しているだけです

移動セマンティクス(r値参照)を使用するサードパーティのライブラリクラスを使用しているとします。その定義は次のとおりです。

class VeryHeavyObject {
    VeryHeavyObject(const VeryHeavyObject& obj); // copy constructor
    VeryHeavyObject& operator= (const VeryHeavyObject& obj); // copy operator

public:
    VeryHeavyObject(); // constructor

    VeryHeavyObject(VeryHeavyObject&& obj); // move constructor
    VeryHeavyObject& operator= (VeryHeavyObject&& obj); // move operator

    // ....
};

どうやら、作者はコピーのコストを本当に心配していて、VeryHeavyObjectすべてを強制的に移動することに決めました(もっと明らかに、彼は移動セマンティクスでクラスを設計する方法を知りません)。しかし、その後、私のコードのある時点で、のコピーが必要になりますVeryHeavyObject

さて、中心的な質問は 、ムーブコンストラクタとムーブ演算子だけでオブジェクトをコピーするにはどうすればよいですか?

PS:試しましたが、図書館の作者に連絡することはできません(彼は休暇中だと思います)。

4

4 に答える 4

6

それはいけません。

ただし、その内部 (getter など) に十分にアクセスできる場合は、自分でクローンを作成できます。

于 2012-11-28T09:29:15.893 に答える
2

それは不可能かもしれません。

クラスはコピーを非公開と宣言しましたが、関数が定義されているかどうかはわかりません。クラスにはコピー操作があり、遅いことをするのを止めるために隠れていると思われるようですが、そうではないかもしれません。一部のオブジェクトは単純にコピーできません。例として、ストリームを考えてみましょう。

C++11 では非公開で宣言されているが定義されていない関数は期待できませんが、それを禁止する法律はありません。とにかく、プライベートコピー機能が実装されていたとしても、それはおそらく何らかの理由でプライベートです(おそらく、特定の制御された状況下でのみ使用できます:クラスの内部はそれを安全に使用する方法を知っていますが、あなたは知りません)。したがって、パブリック コピーがない場合、このクラスの API に関する限り、コピーすることはできません。

おそらく、クラスには十分なパブリック アクセサーがあり、必要な状態を調べて、それに一致する新しいオブジェクトを構築できます。もしそうなら、クラスの作成者に、それが公にコピー可能であるべきだと合理的に不平を言うことができます。そうでない場合は、複製できない状態になっている可能性があります。

何かへの一意のアクセスを提供するもの (ストリーム、ドライバー、ロック) には、コピー可能ではない理由があります。これは、オリジナルとコピーの両方が同じものへの一意のアクセスを提供できないためです。確かにdup、ファイル記述子でさえ、それらをラップするストリームは言うまでもなく、何かへの一意のアクセスを物理的に提供しないことを意味します。ただし、ストリームには、まだ書き込まれていないバッファリングされたデータを含む状態があります。つまり、ストリームをコピーすると、クラスが保護するように設計された複雑さが生じます。したがって、論理的には、通常、何かにアクセスする唯一の方法であるかのようにストリームを使用します。

コピー代入演算子が実装されていれば、 private でも呼び出す方法をハックできるかもしれません。これはコピー コンストラクターでは機能しませんが、コンストラクターへのポインターを取得することはできません。残忍なハックとして、ヘッダーを含める前に可能でした。これは未定義の動作ですが、使用している実装では機能する可能性があります。 #define private publicサードパーティのソースをフォークする方が良いでしょう。

于 2012-11-28T10:06:03.770 に答える
2

明確に定義されたインターフェースであり、これが事実であると想定します。作成者がパフォーマンス上の理由から特定の使用を思いとどまらせたいため、一部のメソッドが利用できない場合があります。よく知られている例は です。これは、 などの他のコンテナと比較して複雑であるため、演算子がstd::list含まれていません。[]O(n)O(1)std::vector

この場合、ライブラリの作成者は、質問で述べているように、非常にコストがかかるため、コピーの使用を思いとどまらせたいと考えています。しかし、これは不可能だという意味ではありません。本当に必要な場合は、元のデータを適切に取得し、これらのデータを使用して新しいものを構築し、 を使用して返す独自のClone()関数を作成できます。インターフェースを持っていないので、それを試みることはできませんが、できると確信しています。VeryHeavyObjectstd::moveVeryHeavyObject

于 2012-11-28T09:24:15.393 に答える
1

一般に、アクセスできないプライベート データが存在する可能性があるため、クラスを変更しないと不可能です。浅いコピーで十分な場合は可能かもしれませmemccpy。(クラスに仮想メンバーまたはポインターがない場合、浅いコピーと深いコピーは同じであることに注意してください)。

于 2012-11-28T09:31:08.393 に答える