40

std::atomic_int変数を使いたい。私のコードには、次のものがあります。

#include <atomic>

std::atomic_int stop = 0;

int main()
{
    // Do something
}

そして、これは私にコンパイルエラーを与えます:

use of deleted function 'std::__atomic_base<_IntTp>::__atomic_base(const std::__atomic_base<_IntTp>&) [with _ITp = int]'
 std::atomic_int stop = 0;
                        ^

何が起こっているかについて何か考えはありますか?

4

2 に答える 2

48

std::atomic_intあなたのコードはRHS でテンポラリを構築しようとしており、std::atomic_intコピー コンストラクタ ( deleted) を使用して次のstopように初期化します。

std::atomic_int stop = std::atomic_int(0);

これは、ここで実行しているcopy-initialisationが他の種類の初期化と完全に同等ではないためです。

[C++11: 8.5/16]:初期化子のセマンティクスは次のとおりです [..]

初期化子が (括弧で囲まれていない) 波括弧初期化リストである場合、オブジェクトまたは参照はリスト初期化されます(8.5.4)。

(これにより、この回答の最後にあるオプション3が可能になります)

[..]

宛先の型が (おそらく cv 修飾された) クラス型の場合:

  • 初期化がdirect-initializationの場合、またはソース型の cv 修飾されていないバージョンが宛先のクラスと同じクラスまたは派生クラスであるcopy-initializationの場合、コンストラクターが考慮されます。適用可能なコンストラクターが列挙され (13.3.1.3)、オーバーロード解決 (13.3) によって最適なコンストラクターが選択されます。そのように選択されたコンストラクターは、引数として初期化式または式リストを使用して、オブジェクトを初期化するために呼び出されます。コンストラクターが適用されない場合、またはオーバーロードの解決があいまいな場合、初期化は不適切な形式です。

(これはコードをほぼ説明していますが、完全ではありません。ここでの鍵は、おそらく直感に反してstd::atomic_int、あなたのケースでは のコンストラクターがまったく考慮されていないことです!)

  • それ以外の場合 (つまり、残りのコピー初期化の場合)、ソースの型から宛先の型に、または (変換関数が使用されている場合は) その派生クラスに変換できるユーザー定義の変換シーケンスは、13.3 で説明されているように列挙されます。 1.4 であり、過負荷解決 (13.3) によって最適なものが選択されます。変換ができないか、あいまいな場合は、初期化の形式が正しくありません。選択された関数は、初期化式を引数として呼び出されます。関数がコンストラクターの場合、呼び出しは、目的の型の cv 修飾されていないバージョンの一時を初期化します。一時的なものは prvalue です。呼び出しの結果 (コンストラクターの場合は一時的なもの) は、直接初期化するために使用されます。、上記の規則に従って、コピー初期化の宛先であるオブジェクト。場合によっては、初期化されるオブジェクトに中間結果を直接構築することにより、この直接初期化に固有のコピーを排除する実装が許可されます。12.2、12.8を参照。

(これはあなたのシナリオです。したがって、コピーは省略できますが、それでも可能である必要があります)

  • [..]

とにかく、これが修正です。直接初期化またはリスト初期化を使用:

std::atomic_int stop(0);     // option 1
std::atomic_int stop{0};     // option 2
std::atomic_int stop = {0};  // option 3
于 2014-12-05T11:09:30.870 に答える