[解決済み] C++11で型を非可動にするのはいつ?
質問
私はこれが私の検索結果に表示されないことに驚きました。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
はまだ
動かせる
であり、コピーは有効な移動操作であるため、言語用語では移動可能です。 しかし、コピーできない型では、メモリの一部を移動したくない、または移動できない場合、またその値をコピーできない場合、それは移動不可となります。ミューテックスやアトミック変数はメモリの特定の場所(特別なプロパティで扱われます)なので、移動する意味がなく、またコピーもできないので、移動不可となります。
関連
-
[解決済み】C++ - 解放されるポインタが割り当てられていないエラー
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み] static_cast, dynamic_cast, const_cast, reinterpret_cast はいつ使うべきですか?
-
[解決済み] スマートポインターとは何ですか?
-
[解決済み] 仮想デストラクタはいつ使うのか?
-
[解決済み] 型名の後の括弧は、newで違いがあるのでしょうか?
-
[解決済み] std::move()とは何ですか?また、どのような場合に使用するのですか?
-
[解決済み] フォワード宣言はどのような場合に使用できますか?
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み】正気で、安全で、効率的な方法でファイルをコピーする。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++ クラスヘッダが含まれているときに「不明な型」があるのはなぜですか?重複
-
[解決済み] string does not name a type Errorが発生するのはなぜですか?
-
[解決済み】デバッグアサーションに失敗しました。C++のベクトル添え字が範囲外
-
[解決済み】Visual Studio 2013および2015でC++コンパイラーエラーC2280「削除された関数を参照しようとした」が発生する
-
[解決済み] 式はクラス型を持つ必要があります。
-
[解決済み】オブジェクト引数のない非静的メンバ関数の呼び出し コンパイラーエラー
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】CMakeエラー at CMakeLists.txt:30 (project)。CMAKE_C_COMPILER が見つかりませんでした。
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない