アトミックのベクトルの初期化


12

考慮してください:

void foo() {
  std::vector<std::atomic<int>> foo(10);
  ...
}

fooの内容は有効ですか?または、明示的にループして初期化する必要がありますか?私はGodboltを確認しましたが、問題はないようですが、この点については標準が非常に混乱しているようです。

std ::ベクトルコンストラクタは、それが挿入言うデフォルトの挿入のインスタンスstd::atomic<int>は、初期化値ビア配置をnew

値の初期化のこの効果は当てはまると思います:

2)Tがユーザー提供でも削除でもないデフォルトコンストラクターを持つクラス型(つまり、暗黙的に定義またはデフォルト化されたデフォルトコンストラクターを持つクラスである可能性がある)である場合、オブジェクトはゼロ初期化され、その後重要なデフォルトコンストラクターがある場合はdefault-initialized。

したがって、アトミックはゼロで初期化されているように思えます。だから問題は、std::atomic<int>有効なオブジェクトの結果のゼロ初期化ですか?

答えは「実際にはそうですが、実際には定義されていません」と思いますか?

注:この回答は、それがゼロで初期化されていることには同意していますが、それがオブジェクトが有効であることを意味するかどうかについては、実際には言っていません。

回答:


7

あなたは心配するのは正しいです。標準によれば、アトミックにはデフォルトのコンストラクターが呼び出されますが、そのように初期化されていません。これは、デフォルトのコンストラクターがアトミックを初期化しないためです。

default-initialized std::atomic<T>Tオブジェクトを含まず、その唯一の有効な用途はstd :: atomic_initによる破棄と初期化 です。

これは、通常の言語規則に多少違反しており、一部の実装はとにかく初期化します(注記したとおり)。

そうは言っても、標準に従って正しく初期化されていることを100%確実にするために、追加のステップを実行することをお勧めします。

ラッパーの使用を含む、問題を回避する多くの方法があります。

struct int_atomic {
   std::atomic<int> atomic_{0};//use 'initializing' constructor
};

または実際に使用しますatomic_init。とにかく問題のコードの周りですでに同期している必要があります
オービットのライトネスレース

デフォルトのコンストラクタは取るに足らないので、とにかく呼び出されません(質問の引用どおり)
Orbitのライトネスレース

@LightnessRaceswithMonicaも可能です。ラッパーを強調したいと思います
darune

@LightnessRaceswithMonicaこれは通常の言語ルールの例外です-一部のコンパイラはこの例外を実装していません。StoreTellerの回答が100%正確かどうかわかりません。
darune

2

デフォルトのコンストラクターが呼び出されたとしても(それは簡単なため、呼び出されません、実際には何もしません

ゼロ初期化は明らかに有効なアトミックを生成することを保証できません。これは、偶然にすべてのメンバーをゼロ初期化して有効なアトミックを作成した場合にのみ機能します。

また、アトミックはコピーできないため、ベクトルコンストラクターで初期化値を指定することはできません。

コンテナーとstd::atomic_init各要素をループする必要があります。これを回避する必要がある場合は、同じ理由ですでにベクターの作成を同期しているので問題ありません。


@daruneそれは一種の同期だと思います;)
オービットでの軽さの
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.