私は以下のようなクラスを持っています。
#include <atomic>
static const long myValue = 0;
class Sequence
{
public:
Sequence(long initial_value = myValue) : value_(initial_value) {}
private:
std::atomic<long> value_;
};
int main()
{
Sequence firstSequence;
Sequence secondSequence = firstSequence;
return 0;
}
このようなコンパイルエラーが発生します、
test.cpp:21:36: error: use of deleted function ‘Sequence::Sequence(const Sequence&)’
test.cpp:5:7: error: ‘Sequence::Sequence(const Sequence&)’ is implicitly deleted because the default definition would be ill-formed:
test.cpp:5:7: error: use of deleted function ‘std::atomic<long int>::atomic(const std::atomic<long int>&)’
このような場合、デフォルトのコピーコンストラクターと代入演算子は機能しませんか?
PS:私はgccバージョン4.6.3を使用しています
すべてのロードとストアは明示的に行われる必要があるため、標準のコピーコンストラクターでアトミックをコピーすることはできません。 Sequence
の独自のコピーコンストラクターを作成する必要があります。これは、value_(rhs.value_.load())
の形式の初期化を行います(おそらく、よりリラックスしたメモリ順序で)。
Atomicはcopy-ctorを削除しました。したがって、クラス内のコピー/移動-ctorは削除されます。
n3337 12.8/11
暗黙的に宣言されたコピー/移動コンストラクターは、そのクラスのインラインパブリックメンバーです。クラスXのデフォルトのコピー/移動コンストラクターは、Xに次の場合、削除済み(8.4.3)として定義されます。
—クラスタイプM(またはその配列)の非静的データメンバー。Mの対応するコンストラクターに適用されるオーバーロード解決(13.3)により、あいまいさまたは関数が削除されるため、コピー/移動できません。またはデフォルトのコンストラクタからアクセスできません、
std::atomic<long int>::atomic(const std::atomic<long int>&)
関数がないため、コンパイラーがSequence
クラスのデフォルトのコピーコンストラクターを作成する方法はありません。そのクラスのコピーコンストラクターが必要な場合(そして必要な場合はSequence secondSequence = firstSequence;
動作する)次に、1つ書く必要があります。
この動作は、標準で要求されています。
アトミック積分とアドレスタイプを以下に示します。これらのタイプは標準レイアウトでなければなりません。それらには、些細なデフォルトコンストラクタ、constexpr明示値コンストラクタ、削除されたコピーコンストラクタ、削除されたコピー代入演算子、および些細なデストラクタが必要です。これらのタイプは、集約初期化構文をサポートする必要があります。
標準でコピーコンストラクタを削除するという選択は、次の2つの理由によると思います。
一般に、ロード/ストアのペアが必要です。 std :: atomicの呼び出し元を制御しない場合に、これが実行されるように強制する方法はありますか?
使用していたstd :: atomic <>タイプがis_lock_free()がfalseである場合(つまり、そのサイズの整数タイプの実装ではミューテックスが必要)、どうしますか?ミューテックスの初期化にはどのコピーセマンティクスを使用しますか?暗黙的にコピーされたミューテックスは、ロックされた状態で不幸にもコピーされる可能性があるため、再初期化する必要があります。このため、std :: mutexにも削除されたコピーコンストラクタがあり、それによって要件がstd :: atomicにもプッシュされると思います。