C++11 で型を移動不可にするのはいつですか? 質問する

C++11 で型を移動不可にするのはいつですか? 質問する

これが検索結果に表示されなかったことに驚きました。C++11 の移動セマンティクスの有用性を考えると、誰かが以前にこれを質問したはずだと思いました。

C++11 でクラスを移動不可にする必要があるのはいつですか (または、移動不可にするのがよいでしょうか)?

(理由他のつまり、既存のコードとの互換性の問題よりも、

ベストアンサー1

ハーブの回答(編集前)は、実際には、すべきではない移動可能: std::mutex

OS のネイティブ ミューテックス タイプ ( pthread_mutex_tPOSIX プラットフォームなど) は「位置不変」ではない可能性があります。つまり、オブジェクトのアドレスはその値の一部です。たとえば、OS はすべての初期化されたミューテックス オブジェクトへのポインターのリストを保持している可能性があります。 にstd::mutexネイティブ OS ミューテックス タイプがデータ メンバーとして含まれていて、ネイティブ タイプのアドレスが固定されている必要がある場合 (OS はミューテックスへのポインターのリストを保持しているため)、ネイティブ ミューテックス タイプをヒープに格納して、オブジェクトstd::mutex間で移動したときに同じ場所に留まるようにするか、を移動しないようにする必要があります。 にはコンストラクタがあり、 は定数初期化 (つまり静的初期化) の対象である必要があるため、プログラムの実行が開始される前にグローバルが構築されることが保証され、そのコンストラクタは を使用できないため、ヒープに格納することはできません。したがって、 を移動不可にすることが唯一の選択肢です。std::mutexstd::mutexstd::mutexconstexprstd::mutexnewstd::mutex

固定アドレスを必要とするものを含む他のタイプにも同じ論理が当てはまります。リソースのアドレスを固定したままにする必要がある場合は、移動しないでください。

移動しないことのもう 1 つの理由は、std::mutex安全に行うことが非常に難しいということです。なぜなら、移動している瞬間に誰もミューテックスをロックしようとしていないことを確認する必要があるからです。ミューテックスはデータ競合を防ぐために使用できる構成要素の 1 つなので、ミューテックス自体が競合に対して安全でないとしたら残念なことです。移動不可能なオブジェクトの場合、構築されてからstd::mutex破棄されるまでは、誰でもロックとロック解除しか実行できないことがわかっています。また、これらの操作はスレッド セーフであり、データ競合を引き起こさないことが明示的に保証されています。この同じ議論はstd::atomic<T>オブジェクトにも当てはまります。オブジェクトをアトミックに移動できない限り、安全に移動することはできません。別のスレッドが、compare_exchange_strongオブジェクトが移動されている瞬間にそのオブジェクトを呼び出そうとしている可能性があります。したがって、型を移動できないもう 1 つのケースは、安全な並行コードの低レベルの構成要素であり、すべての操作のアトミック性を確保する必要がある場合です。オブジェクトの値がいつでも新しいオブジェクトに移動される可能性がある場合は、アトミック変数を使用してすべてのアトミック変数を保護し、使用しても安全か、移動済みかを確認する必要があります。また、そのアトミック変数を保護するアトミック変数などを使用する必要があります。

一般論として、オブジェクトが単なるメモリの断片であり、値や値の抽象化を保持する型ではない場合、それを移動しても意味がないと言えると思います。 などの基本型は移動できませんint。移動しても単なるコピーです。 の中身を抜き取ることはできませんがint、その値をコピーしてゼロに設定することはできます。しかし、それは依然としてint値を持つ であり、単なるメモリのバイトです。 しかし、 はint依然として移動可能な言語用語では、コピーは有効な移動操作であるため、移動できません。ただし、コピー不可能な型の場合、メモリの一部を移動したくない、または移動できず、その値をコピーすることもできない場合は、移動できません。ミューテックスまたはアトミック変数は、メモリの特定の場所 (特別なプロパティで処理されます) であるため、移動しても意味がなく、コピーもできないため、移動できません。

おすすめ記事