Let's say I have a class with a member array of std::atomic
s, where the
array is sized via a computation (i.e. it may change based on other constants elsewhere in the program):
class Foo {
static constexpr size_t kArraySize = ComputeArraySize();
std::atomic<size_t> atomics_[kArraySize];
};
What is the most elegant way to ensure that the atomics are all initialized to
zero? Can I do better than looping over the array in Foo
's constructor and
explicitly storing zero? Does the answer differ for std::array
?
Normally I would use a brace initializer here, but the derived length (which may be long) makes it difficult.
Note that I cannot assume that the instance of Foo
has static storage
duration.
There are two ways to specify initializers for arrays: With C89-style initializers, array elements must be initialized in subscript order. Using designated initializers, which allow you to specify the values of the subscript elements to be initialized, array elements can be initialized in any order.
int num[5] = {1, 1, 1, 1, 1}; This will initialize the num array with value 1 at all index. The array will be initialized to 0 in case we provide empty initializer list or just specify 0 in the initializer list. Designated Initializer: This initializer is used when we want to initialize a range with the same value.
1. Using Initializer List. int arr[] = { 1, 1, 1, 1, 1 }; The array will be initialized to 0 if we provide the empty initializer list or just specify 0 in the initializer list.
Okay, I believe I've worked this through. Both of these will initialize all of the atomics to zero:
std::atomic<size_t> plain_array[kArraySize] = {};
std::array<std::atomic<size_t>, kArraySize> std_array = {};
Here's the logic:
[dcl.init.aggr]/1 defines arrays to be aggregates.
[array.cons]/1 mandates that std::array
also be an aggregate.
[dcl.init.aggr]/7 says that if there are fewer elements of the initializer list than there are members in the aggregate, then the remaining members shall be initialized from an empty initializer list. In this case, that's all members.
[dcl.init.list]/3 defines list-initialization from an empty list for a class
with a default constructor (as with std::atomic
) to cause
value-initialization.
[dcl.init]/7 says that classes without user-provided constructors are
zero-initialized. Assuming that std::array<T>
contains an array of T
,
and that the zero representation of std::atomic<size_t>
is what we expect,
then we're good.
Now, std::atomic
does have a user-provided constructor, just not a
user-provided default constructor (the latter is explicitly defaulted). So
it doesn't technically fit the conditions of the last point. But it seems this
is an error in the standard, and has been fixed in more recent
drafts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With