5

When an array is default initialized, is the order in which it's elements are default initialized defined by the C++ standard?

To give an example, is the following C++ program guaranteed do print strictly ascending memory addresses?

#include <iostream>
struct Foo{
    Foo() {
        std::cout << this << std::endl;
    }
};
int main() {
    delete[] new Foo[10];
    return 0;
}

I found the following in the Standard under 9.4.1 Initializers, General:

7 To default-initialize an object of type T means: (...)

(7.2)— If T is an array type, each element is default-initialized.

Am I correct in assuming that this means that it's unspecified, or is this clarified somewhere else in the document?

This answer claims that It's defined (under (a)), but (afaict) does not provide any evidence for that.

Note that I'm not trying to refer to the array itself before it is initialized (Can a (C/C++) array initialization reference itself?), but simply care about observable side effects of the initialization order.

Botje
  • 26,269
  • 3
  • 31
  • 41
ChrisB
  • 1,540
  • 6
  • 20
  • Incidentally, the output in the code in the question doesn't need the extra stuff that `std::endl` does. `'\n'` ends a line. – Pete Becker Mar 17 '23 at 15:24
  • § 9.4.17.5 specifies *how* to initialize arrays, but makes no mention of order – Mooing Duck Mar 17 '23 at 15:27
  • afaik when the elements are initialized in order it is not guaranteed to get strictly increasing memory addresses printed. `<` is unspecified for pointers, so "strictly increasing" isnt well defined. (I suppose thats not the actual point of the question, but you could use a static `int` counter as well to assert the order of initialization) – 463035818_is_not_an_ai Mar 17 '23 at 16:13
  • 1
    @463035818_is_not_a_number: Since the elements are part of an array, the < operator is well defined on pointers to it's members: https://stackoverflow.com/questions/44397784/is-operator-less-than-on-pointers-consistent – ChrisB Mar 17 '23 at 16:15
  • @ChrisB I wasnt aware. Thanks for the link – 463035818_is_not_an_ai Mar 17 '23 at 16:16

1 Answers1

4

The latest draft (N4917) has this to say under 9.4.2 Aggregates, item 7 ([dcl.init.aggr]):

The initializations of the elements of the aggregate are evaluated in the element order. That is, all value computations and side effects associated with a given element are sequenced before those of any element that follows it in order.

So you can depend on the order.

molbdnilo
  • 64,751
  • 3
  • 43
  • 82
  • 1
    Just a side-note that this wording isn't particularly new either. It goes back to at least N4800, from January of 2019 (the oldest draft I have handy). – Jerry Coffin Mar 17 '23 at 15:28
  • 2
    I was certain that the rule has been this way since forever, as it is the simplest and most efficient implementation (at least I think it is), but C++11 only mentions the order when there is an initializer, and C++03 has nothing to say about the order at all. (Or it's hidden in a non-obvious place in those two.) – molbdnilo Mar 17 '23 at 15:41
  • 2
    C++98 [class.init]/3: "When an array of class objects is initialized (either explicitly or implicitly), the constructor shall be called for each element of the array, following the subscript order; see 8.3.4. [*Note:* destructors for the array elements are called in reverse order of their construction. ]" – Brian Bi Mar 18 '23 at 00:38
  • @BrianBi Oh, it was in the other obvious place... – molbdnilo Mar 18 '23 at 07:38