1. ホーム
  2. c++

[解決済み] C++11で型を非可動にするのはいつ?

2022-07-12 13:39:42

質問

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

C++11 では、いつクラスを移動不可にする必要がありますか (または、するのが良いアイデアですか)。

(理由 その他 既存のコードとの互換性の問題以外の理由、です)。

どのように解決するのですか?

Herbの回答(編集される前のもの)は、実際に、以下のような型の良い例を示していました。 を使用すべきではありません。 は移動可能であるべきではないのです。 std::mutex .

OSのネイティブなミューテックスタイプ(例えば pthread_mutex_t は、オブジェクトのアドレスがその値の一部であるという意味で、quot;location invariant" でない場合があります。例えば、OS は初期化されたすべてのミューテックスオブジェクトへのポインタのリ ストを保持しているかもしれません。もし std::mutex がデータメンバとして OS のネイティブな Mutex 型を含んでいて、ネイティブな型のアドレスが固定でなければならない場合 (OS がその Mutex へのポインタのリストを保持しているため)、どちらかが std::mutex の間を移動しても同じ場所に留まるように、ネイティブの Mutex 型をヒープ上に格納しなければなりません。 std::mutex オブジェクトの間を移動したり std::mutex が動いてはいけません。ヒープに保存することは不可能です、なぜなら std::mutex には constexpr のコンストラクタを持ち、定数初期化 (すなわち静的初期化) が可能である必要があります。 std::mutex はプログラムの実行が始まる前に構築されることが保証されているため、そのコンストラクタでは new . したがって、残された唯一の選択肢は std::mutex を不動にすることです。

同じ理由が、固定されたアドレスを必要とするものを含む他の型にも当てはまります。リソースのアドレスが固定されていなければならないのであれば、それを動かさないようにしましょう!

を動かしてはいけないという別の議論もあります。 std::mutex というのも、移動される瞬間に誰もそのミューテックスをロックしようとしていないことを知る必要があるからです。ミューテックスはデータ競合を防ぐための構成要素のひとつですから、競合そのものに対して安全でないのは残念なことです。 移動不可能な std::mutex では、一度構築された後、破壊される前に誰もができる唯一のことは、ロックとアンロックであり、これらの操作はスレッドセーフでデータ競合を引き起こさないことが明確に保証されています。 これと同じ議論が std::atomic<T> オブジェクトにも当てはまります。アトミックに移動できない限り、安全に移動させることはできませんし、他のスレッドが compare_exchange_strong を呼び出そうとするかもしれません。つまり、型が移動可能であってはならないもう一つのケースは、安全な同時実行コードの低レベルの構成要素であり、それに対するすべての操作の原子性を保証しなければならない場合です。 オブジェクトの値がいつでも新しいオブジェクトに移動できる場合は、アトム変数を使用してすべてのアトム変数を保護し、それを使用しても安全か移動されたかを知る必要があります。

オブジェクトが単なる純粋なメモリの一部であり、値のホルダーや値の抽象化として機能する型ではない場合、それを移動するのは意味がない、と一般化できると思うのです。 のような基本的な型は int のような基本的な型は移動できません。移動しても単なるコピーに過ぎません。移動は単なるコピーです。 int の中身を引き抜くことはできませんが、その値をコピーしてゼロにすることはできますし、それはまだ int であり、それは単なるメモリのバイトです。しかし int はまだ 動かせる であり、コピーは有効な移動操作であるため、言語用語では移動可能です。 しかし、コピーできない型では、メモリの一部を移動したくない、または移動できない場合、またその値をコピーできない場合、それは移動不可となります。ミューテックスやアトミック変数はメモリの特定の場所(特別なプロパティで扱われます)なので、移動する意味がなく、またコピーもできないので、移動不可となります。