27
struct MyClass
{
  std::array<int, 10> stdArr;

  MyClass() : stdArr()
  {}
};

MyClass c;

Questions:

  1. Is c.stdArr zero-initialized?
  2. If yes - why?

My own contradictory answers:

  1. It is zero-initialized: std::array wants to behave like a c-array. If in my example above stdArr was a c-array, it would be zero-initialized by stdArr() in the initialization list. I expect that writing member() inside of an initialization list initializes the object.

  2. It's not zero-initialized:

    • std::array normally has a single member which is in my case int[10] _Elems;
    • normally fundamental types and arrays of fundamental types like int[N] are not default-initialized.
    • std::array is an aggregate type which implies that it is default-constructed.
    • because there is no custom constructor which initializes _Elems, I think it is not zero-initialized.

What's the correct behaviour of std::array according to the C++11 Standard?

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
Peter
  • 373
  • 3
  • 5
  • [CPP Reference says](http://en.cppreference.com/w/cpp/container/array) that aggregate initialization works on `std::array`, i. e. elements **are** zero-initialized. –  Jun 25 '13 at 12:33
  • @H2CO3 The fact that aggregate initialisation works means that it can be initialised using `{ ... }` syntax. That isn't relevant here, there is no aggregate initialisation. –  Jun 25 '13 at 12:37
  • I linked another question that has complete explanation of when it is default-initialized and when it is zero-initialized. – Jan Hudec Apr 20 '16 at 13:34

2 Answers2

21

Is c.stdArr zero-initialized?

Yes

If yes - why?

This performs a value initialization of stdArr:

MyClass() : stdArr() {}

In this context, the effect of the value initialization is a zero initialization of the object.

Edit: there is plenty of relevant information in What are Aggregates and PODs...?

Community
  • 1
  • 1
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • 4
    I would have expected that `: stdArr()` simply calls the std::array default constructor, which does nothing!? – Martin85 Jun 25 '13 at 13:04
  • 4
    @Martin85 that is not how it works. One would have to provide a user defined default constructor that does nothing (rendering `std::array` a non-aggregate in the process). This is a handle C++ gives us to zero-initialize PODs and aggregates. – juanchopanza Jun 25 '13 at 13:07
  • 1
    [(Horrible) live example](http://ideone.com/Y8AXoM) (by no means a proof, I know) – gx_ Jun 25 '13 at 13:47
  • Thanks for the precise answer and the links. – Peter Jun 25 '13 at 13:48
  • @gx_ in your tests, if we look at A1 and A2, they have non zero values when initialized by default. Which means you get zero-init only when using value initialization (`{}`). When you use default initialization (nothing, i.e. A1 and A2) you get random crap (no-init). be it `std array` or `c array`. – v.oddou Jul 16 '15 at 08:30
0

"std::array wants to behave like a c-array" is not how the standard describes behavior. It's a user-defined type, and members of user-defined types are initialized by calling their constructor, i.e. array<int,10>::array()

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 10
    `std::array` doesn't have a constructor. – R. Martinho Fernandes Jun 25 '13 at 12:54
  • Ok, let's better say, I want to behave std::array like a c-array. But am I right, you think `c.stdArr` is initialized in my code snippet? Thanks. – Peter Jun 25 '13 at 12:56
  • @R.MartinhoFernandes: It's not deleted, so it does have one: the compiler-generated one. – MSalters Jun 25 '13 at 13:02
  • @R.MartinhoFernandes, then how does it work with initializer_list ? – sasha.sochka Jun 25 '13 at 13:10
  • @sasha.sochka it does not http://coliru.stacked-crooked.com/view?id=32781f14670c8ccc79670abf2bca66f5-8dcf59174449f11e872bc3faded12b76. – R. Martinho Fernandes Jun 25 '13 at 13:10
  • 1
    @MSalters it's not callable in any way. – R. Martinho Fernandes Jun 25 '13 at 13:13
  • @R.MartinhoFernandes for me this piece of code works. And it uses initializer_list `array a { {1,2,3,4,5}};` – sasha.sochka Jun 25 '13 at 13:15
  • 1
    @sasha.sochka no, it does use initializer_list. It's aggregate initialisation. See http://coliru.stacked-crooked.com/view?id=0243724bed66c7d8c6d70275ba07a61e-8dcf59174449f11e872bc3faded12b76 and http://coliru.stacked-crooked.com/view?id=7fc7cf92253d2f2aead7d08451346bec-8dcf59174449f11e872bc3faded12b76 – R. Martinho Fernandes Jun 25 '13 at 13:16
  • @R.MartinhoFernandes, OK, but if it's an aggr. init., then there should be a public member which corresponds to underlying C-array. – sasha.sochka Jun 25 '13 at 13:19
  • Compare http://en.cppreference.com/w/cpp/language/aggregate_initialization with http://en.cppreference.com/w/cpp/language/list_initialization – R. Martinho Fernandes Jun 25 '13 at 13:19
  • @sasha.sochka only if you are implementing this in user code. `std::array` is required to be an aggregate, but the standard library can use compiler magic for this. Yes, a public array member is the simplest implementation, but not in any way the only one allowed. – R. Martinho Fernandes Jun 25 '13 at 13:20
  • @sasha.sochka the C++11 standard did not even specify that it must have a single array data member (although it presented an "example" using such an implementation). – juanchopanza Jun 25 '13 at 13:23
  • Well, see http://en.cppreference.com/w/cpp/container/array: "This container is an aggregate type with the same semantics as a struct holding a C-style array `T[N]` as its only non-static data member. It can be initialized with aggregate-initialization, given at most N initializers that are convertible to `T`: `std::array a = {1,2,3};`" – R. Martinho Fernandes Jun 25 '13 at 13:25
  • @R.MartinhoFernandes: If the compiler generated `array::array()` is not callable, then what is called in the statement `array::array();` ? (Expression statement, creates temporary and immediately discards it.) "An aggregate is an array or a class (Clause 9) with no **user-provided** constructors (12.1)," – MSalters Jun 25 '13 at 18:34
  • @MSalters nothing. That's not a valid expression. You cannot call constructors directly. http://coliru.stacked-crooked.com/view?id=b6f2b7a51de4ad1d03081e3ab95a6192-7063104e283ed82d51a6fde7370c6e59 – R. Martinho Fernandes Jun 25 '13 at 21:27