web-dev-qa-db-ja.com

std :: atomicメンバー変数を持つクラスのコピーコンストラクタ/代入演算子でエラーが発生しました

私は以下のようなクラスを持っています。

#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を使用しています

23
polapts

すべてのロードとストアは明示的に行われる必要があるため、標準のコピーコンストラクターでアトミックをコピーすることはできません。 Sequenceの独自のコピーコンストラクターを作成する必要があります。これは、value_(rhs.value_.load())の形式の初期化を行います(おそらく、よりリラックスしたメモリ順序で)。

23
Kerrek SB

Atomicはcopy-ctorを削除しました。したがって、クラス内のコピー/移動-ctorは削除されます。

n3337 12.8/11

暗黙的に宣言されたコピー/移動コンストラクターは、そのクラスのインラインパブリックメンバーです。クラスXのデフォルトのコピー/移動コンストラクターは、Xに次の場合、削除済み(8.4.3)として定義されます。

—クラスタイプM(またはその配列)の非静的データメンバー。Mの対応するコンストラクターに適用されるオーバーロード解決(13.3)により、あいまいさまたは関数が削除されるため、コピー/移動できません。またはデフォルトのコンストラクタからアクセスできません、

7
ForEveR

std::atomic<long int>::atomic(const std::atomic<long int>&)関数がないため、コンパイラーがSequenceクラスのデフォルトのコピーコンストラクターを作成する方法はありません。そのクラスのコピーコンストラクターが必要な場合(そして必要な場合はSequence secondSequence = firstSequence;動作する)次に、1つ書く必要があります。

この動作は、標準で要求されています。

アトミック積分とアドレスタイプを以下に示します。これらのタイプは標準レイアウトでなければなりません。それらには、些細なデフォルトコンストラクタ、constexpr明示値コンストラクタ、削除されたコピーコンストラクタ、削除されたコピー代入演算子、および些細なデストラクタが必要です。これらのタイプは、集約初期化構文をサポートする必要があります。

6
David Schwartz

標準でコピーコンストラクタを削除するという選択は、次の2つの理由によると思います。

  • 一般に、ロード/ストアのペアが必要です。 std :: atomicの呼び出し元を制御しない場合に、これが実行されるように強制する方法はありますか?

  • 使用していたstd :: atomic <>タイプがis_lock_free()がfalseである場合(つまり、そのサイズの整数タイプの実装ではミューテックスが必要)、どうしますか?ミューテックスの初期化にはどのコピーセマンティクスを使用しますか?暗黙的にコピーされたミューテックスは、ロックされた状態で不幸にもコピーされる可能性があるため、再初期化する必要があります。このため、std :: mutexにも削除されたコピーコンストラクタがあり、それによって要件がstd :: atomicにもプッシュされると思います。

0
Peeter Joot