5

何らかの種類のクラスまたは構造があるとします。仮想関数などはなく、いくつかのカスタム コンストラクターと、デストラクターでのクリーンアップが必要ないくつかのポインターだけです。

この構造体で memcpy または memmove を使用すると、悪影響はありますか? 移動した構造を削除すると問題が発生しますか? 質問は、メモリの配置も正しいことを前提としており、安全なメモリにコピーしています。

4

5 に答える 5

9

一般的なケースでは、はい、問題があります。memcpyとはどちらも、memmoveそれ以上のセマンティクスを持たないビット演算です。オブジェクトを移動するのに十分ではないかもしれません*し、コピーするのに十分でないことは明らかです。

コピーの場合、複数のオブジェクトが動的に割り当てられた同じメモリを参照し、複数のデストラクタがそれを解放しようとするため、コピーが壊れます。shared_ptr所有権の共有は/が提供しないさらなるセマンティクスの一部であるため、 のようなソリューションはここでは役に立たないことに注意してください。memcpymemmove

移動する場合、およびタイプによっては、場合によっては回避できる場合があります。ただし、オブジェクトが移動される要素へのポインター/参照 (自己参照を含む) を保持している場合、ポインターはビットごとにコピーされ (ここでも、コピー/移動のセマンティクスはありません)、古い場所を参照するため、機能しません。

一般的な答えは同じです:しないでください。


*正確な C++11 の意味でここに移動しないでください。を使用してバッファを拡張しながらオブジェクトを移動できるようにするために特別なタグを使用する標準ライブラリ コンテナの実装を見てきましたが、オブジェクトが に配置された後、を介してオブジェクトを安全に移動memcpyできるようにマークする格納された型に明示的な注釈が必要でした。デストラクタを呼び出さに古いバッファが破棄された新しいバッファ(C++11の移動では、オブジェクトを破壊可能な状態にしておく必要がありますが、このハックでは実現できません)memcpy

于 2012-08-27T03:16:54.860 に答える
5

一般に、クラスベースのオブジェクトでmemcpyを使用することはお勧めできません。最も可能性の高い問題は、ポインタをコピーしてから削除することです。代わりに、コピーコンストラクタまたは代入演算子を使用する必要があります。

于 2012-08-27T03:04:26.460 に答える
4

いいえ、これをしないでください。

memcpyデストラクタが内部のポインタを削除する構造体の場合、構造体の2番目のインスタンスが何らかの方法で破棄されると、二重削除を実行することになります。

C ++イディオムは、std::copy範囲/シーケンス/コンテナーをコピーするためのクラスやその仲間のコピーコンストラクターです。

于 2012-08-27T03:05:43.233 に答える
4

C++11 を使用している場合は、std::is_trivially_copyablememcpyを使用して、 またはを使用してオブジェクトをコピーまたは移動できるかどうかを判断できますmemmove。ドキュメントから:

自明にコピー可能な型のオブジェクトは、std::memcpy で安全にコピーしたり、std::ofstream::write()/std::ifstream::read() でバイナリ ファイルとの間でシリアライズしたりできる唯一の C++ オブジェクトです。一般に、自明にコピー可能な型とは、基になるバイトを char または unsigned char の配列および同じ型の新しいオブジェクトにコピーできる型であり、結果のオブジェクトは元のオブジェクトと同じ値になります。

多くのクラスはこの説明に当てはまらず、クラスが変更される可能性があることに注意する必要があります。C++ オブジェクトでmemcpy/を使用する場合は、何らかの方法で不要な使用を保護することをお勧めします。memmoveたとえば、コンテナ クラスを実装している場合、コンテナが保持する型を簡単に変更して、単純にコピーできなくなるようにすることができます (たとえば、誰かが仮想関数を追加するなど)。でこれを行うことができますstatic_assert

template<typename T>
class MemcopyableArray
{
    static_assert(std::is_trivially_copyable<T>::value, "MemcopyableArray used with object type that is not trivially copyable.");
    // ...
};
于 2016-10-19T10:00:44.637 に答える
3

他の回答がすでに指摘しているように最も重要な問題である安全性は別として、特に小さなオブジェクトの場合、パフォーマンスの問題もある可能性があります。

単純な POD 型の場合でも、コピー コンストラクターの初期化子リストで適切な初期化を行う (または使用法に応じて代入演算子で代入する) 方が、組み込みバージョンのmemcpy. これは、単語のアラインメント、オーバーラップ、バッファ/メモリ アクセス権などをチェックする memcpy のエントリ コードが原因である可能性が非常に高いです。Visual C++ 10.0 以降では、具体的な例を挙げると、memcpy がその論理関数を開始する前に、さまざまなことをテストする多くのプリアンブル コードが実行されます。

于 2012-08-27T03:14:51.317 に答える