145

With C++11 std::array, do I have the guarantee that the syntax std::array<T, N> x; will default-initialize all the elements of the array ?

EDIT: if not, is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?

EDIT: on cppreference, the default constructor description says:

(constructor) (implicitly declared) (public member function)
default-constructs or copy-constructs every element of the array 

so the answer may be yes. But I would like to be sure of that according to the standard or future standard.

ks1322
  • 33,961
  • 14
  • 109
  • 164
Vincent
  • 57,703
  • 61
  • 205
  • 388
  • Don't think so. It's default declared so it's basically the equivalent of the `T x[N]` syntax. – Rapptz Aug 18 '13 at 03:11

5 Answers5

213

By definition, default initialization is the initialization that occurs when no other initialization is specified; the C++ language guarantees you that any object for which you do not provide an explicit initializer will be default initialized (C++11 §8.5/11). That includes objects of type std::array<T, N> and T[N].

Be aware that there are types for which default initialization has no effect and leaves the object's value indeterminate: any non-class, non-array type (§8.5/6). Consequently, a default-initialized array of objects with such types will have indeterminate value, e.g.:

int plain_int;
int c_style_array[13];
std::array<int, 13> cxx_style_array;

Both the c-style array and std::array are filled with integers of indeterminate value, just as plain_int has indeterminate value.

Is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?

I'm guessing that when you say "to their default value" you really mean "initialize all elements to T{}". That's not default-initialization, it is value-initialization (8.5/7). You can request value initialization quite easily in C++11 by giving each declaration an empty initializer:

int plain_int{};
int c_style_array[13]{};
std::array<int, 13> cxx_style_array{};

Which will value-initialize all of the array elements in turn, resulting in plain_int, and all the members of both kinds of arrays, being initialized to zero.

Casey
  • 41,449
  • 7
  • 95
  • 125
  • What about if it's a class member: struct X { std::array dozen; X( ) :dozen( ) {} Does that get me twelve zeros? – gerardw Oct 09 '13 at 17:10
  • 4
    @gerardw According to the standard, yes it does. Beware bugs in MSVC, it fails to implement some cases of value initialization correctly. – Casey Oct 14 '13 at 14:03
  • 1
    indeed boost says so and workaround it with their `boost::value_initialized` [link](http://www.boost.org/doc/libs/1_55_0/libs/utility/value_init.htm) but I believe VC12 (VS2013) has a much better support now. – v.oddou Jun 04 '15 at 07:01
  • 1
    Makes me wish the comitee changed the standard to default value-initialization and undermined value at request. Ie std::array = {std::undetermined}; or something – Viktor Sehr Sep 12 '17 at 12:33
  • In practice what does it even mean to initialize something to an indeterminate value? What's the alternative? – Andrew Nov 30 '17 at 19:42
  • 2
    @Andrew The alternative is that it does something other than initialising it to a defined value. Basically the compiler is free to do whatever is convenient. In practice this often means that in debug mode you'll get a specific weird not-zero value and in release mode you'll get whatever garbage happened to be left in that stack space from some other function (or occasionally zero by coincidence) -- ie. the compiler simply doesn't initialise at all. As for why you'd ever want that: it's faster -- as long as you promise you'll write some other value before you try to read it. – Miral Mar 12 '20 at 03:49
  • @Casey, what does mean `plain_old_int`? – Evandro Coan Apr 13 '21 at 18:59
  • 1
    @user It's an error; `plain_int` was intended. Fixed. – Casey Apr 15 '21 at 20:24
  • @gerardw What's struct X { std::array dozen; X( ) :dozen( ) {}? clerical error? – John Oct 09 '21 at 01:56
  • @Casey Any difference between `char myarray[ARRAY_SIZE] {0};` and `char myarray[ARRAY_SIZE] {};`? – John Oct 09 '21 at 01:57
  • @Casey As you say "there are types for which default initialization has no effect and leaves the object's value indeterminate: any non-class, ***non-array*** type (§8.5/6)." But `int c_style_array[13];` is **array**, why its "default initialization has no effect"? – John Oct 09 '21 at 01:59
33

Default-initialization is a term from the Standard potentially meaning no initialization at all, so you probably mean zero-initialization.

The description at cppreference.com is actually a bit misleading. std::array is an aggregate class, and if the element type is primitive, it is POD: "plain old data," with semantics closely matching the C language. The implicitly-defined constructor of std::array< int, N > is a trivial one which does absolutely nothing.

Syntax like std::array< int, 3 >() or std::array< int, 3 > x{} which provide zeroed values do not do so by invoking a constructor. Getting zeroes is part of value-initialization, specified in C++11 §8.5/8:

To value-initialize an object of type T means:

— if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized …, and if T has a non-trivial default constructor, the object is default-initialized;

std::array has no user-provided default constructor, so it gets zero-initialized. It has an implicitly-defined default constructor, but it is trivial, so it is never default-initialized. (But this doesn't make a difference since trivial initialization by definition has no effect at runtime.)

if not, is there a syntax that will work on all arrays (including zero-sized arrays) to initialize all elements to their default value?

C-style arrays and std::array are both aggregates, and the way to completely zero-initialize any aggregate is with the syntax = {}. This works since C++98. Note that C-style arrays cannot have zero extent, and that sizeof (std::array< X, 0 >) is not zero.

Community
  • 1
  • 1
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • “Syntax like std::array< int, 3 >() or std::array< int, 3 > x{} which provide zeroed values **do not do so by invoking a constructor**.” What's that? What do you intend to tell us?Could you please explain that in more detail? – John Oct 09 '21 at 02:28
14

Both T x[N]; and std::array<T, N> x; default-initialize every element of the array.

For example, if T = std::string, every element will be an empty string. If T is a class without a default constructor, both will fail to compile. If T = int, every element will have indeterminate value (unless that declaration happens to be at namespace scope)

Cubbi
  • 46,567
  • 13
  • 103
  • 169
5

C++11 std::array::fill is a good option for some cases.

Assaf Raman
  • 59
  • 1
  • 1
0

First of all, T x[N] does default initialize the elements, although default initialization of a scalar type T actually does nothing. The above also holds for std::array x. I think what you need is list initialization.

Lingxi
  • 14,579
  • 2
  • 37
  • 93