ハーブの回答(編集前)は、実際には移動可能ではないタイプの良い例を示しています:std::mutex
。
OSのネイティブミューテックスタイプ(pthread_mutex_t
POSIXプラットフォームなど)は、「ロケーションインバリアント」ではない可能性があります。これは、オブジェクトのアドレスがその値の一部であることを意味します。たとえば、OSは初期化されたすべてのミューテックスオブジェクトへのポインタのリストを保持する場合があります。場合はstd::mutex
含まれて(OSはそのミューテックスへのポインタのリストを維持しているため)データメンバとネイティブ型のアドレスなどのネイティブOSのmutex型は、どちらか固定滞在する必要がありstd::mutex
、それはで滞在するので、ヒープ上のネイティブmutex型を格納する必要がありますstd::mutex
オブジェクト間で移動したときと同じ場所、またはstd::mutex
移動してはいけません。にstd::mutex
はconstexpr
コンストラクタがあり、定数初期化(つまり静的初期化)に適格でなければならないため、ヒープに格納することはできません。std::mutex
プログラムの実行が開始する前に構築されることが保証されているため、そのコンストラクタはを使用できませんnew
。したがって、残された唯一の選択肢はstd::mutex
不動であることです。
同じ理由が、固定アドレスを必要とする何かを含む他のタイプにも当てはまります。リソースのアドレスを固定したままにする必要がある場合は、移動しないでください。
移動std::mutex
していないときにmutexをロックしようとしている人がいないことを知っている必要があるため、安全に移動するのは非常に難しいという別の議論があります。mutexはデータの競合を防ぐために使用できる構成要素の1つであるため、競合自体に対して安全でなかった場合は残念です。不動のstd::mutex
場合、いったん構築されて破棄される前に誰でもそれに対して実行できる唯一のことは、ロックとロック解除であり、それらの操作はスレッドセーフであることが明示的に保証されており、データの競合を招くことはありません。これと同じ引数がstd::atomic<T>
オブジェクトに適用されます。オブジェクトをアトミックに移動できない場合、オブジェクトを安全に移動することができない場合、別のスレッドが呼び出しを試みている可能性がありますcompare_exchange_strong
動かされた瞬間のオブジェクト。したがって、型を移動できない別のケースは、型が安全な並行コードの低レベルのビルディングブロックであり、型に対するすべての操作の原子性を保証する必要がある場合です。オブジェクトの値がいつでも新しいオブジェクトに移動される可能性がある場合は、アトミック変数を使用してすべてのアトミック変数を保護する必要があるため、それを使用しても安全であるか、移動されたかがわかります...そのアトミック変数など...
オブジェクトが純粋なメモリの一部であり、値または値の抽象化のホルダーとして機能するタイプではない場合、それを移動することは意味がないと一般的に言っていると思います。int
移動できないなどの基本的なタイプ:移動は単なるコピーです。根性をから引き出すことはできません。int
その値をコピーしてゼロに設定することはできますが、それでもint
値を持つ、それは単なるメモリのバイトです。しかし、int
まだ移動可能ですコピーは有効な移動操作だからです。ただし、コピー不可能なタイプの場合、メモリの一部を移動したくない、または移動できず、その値もコピーできない場合は、移動できません。ミューテックスまたはアトミック変数は、メモリの特定の場所(特別なプロパティで処理される)であるため、移動しても意味がなく、コピーもできないため、移動できません。