Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I elegantly initialize an array of std::atomic?

Tags:

c++

c++11

Let's say I have a class with a member array of std::atomics, 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.

like image 917
jacobsa Avatar asked Jun 19 '14 03:06

jacobsa


People also ask

What is the best possible way to initialize an array?

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.

How do you initialize an entire array?

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.

How do you initialize all elements in an array to a value in C++?

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.


1 Answers

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.

like image 198
jacobsa Avatar answered Oct 17 '22 06:10

jacobsa