# Why does std::complex<> initialize its value to 0 upon default construction?

Doing so strikes me as a waste of time. Consider

std::complex<double> *a = new std::complex<double>[1<<28];


This could be near-instantaneous and only grab pages once they're used, except it isn't.

It appears I'm not the only one bothered by this:

http://listengine.tuxfamily.org/lists.tuxfamily.org/eigen/2011/01/msg00124.html

GCC's libstdc++ (4.6.3) even gloats with this fact:

  ///  Default constructor.  First parameter is x, second parameter is y.
///  Unspecified parameters default to 0.
_GLIBCXX_CONSTEXPR complex(const _Tp& __r = _Tp(), const _Tp& __i = _Tp())
: _M_real(__r), _M_imag(__i) { }


Worse, since the C++ standard doesn't specify a default constructor, this behavior may even be required. (Is this true?)

• Why not use a vector and reserve? std::vector<std::complex<double> > a; followed by a.reserve(1<<28); – James Custer Apr 21 '12 at 0:08
• Also, the standard does specify a default constructor. It is the one you quoted. It would be illegal to declare complex() along with a constructor that takes all default parameters. – James Custer Apr 21 '12 at 0:16
• @James: You still can't e.g. parallel initialize the memory. – Ben Voigt Apr 29 '12 at 21:12

• This is a disaster in a threaded environment: the thread issuing new faults the entire array, causing all the memory to reside on one memory bus. If you subsequently access it simultaneously from threads, the aggregate memory bandwidth will be the bandwidth of that one bus. It's generally preferable to allocate the array with a prescribed memory policy (e.g. via libnuma) or to allocate the array without faulting it and subsequently fault the array with thread ownership distributed as it will be used so that it gets distributed across all memory buses. Yet another reason to avoid C++ new. – Jed Brown Apr 22 '12 at 20:09
• @Wolfgang: Formally, that also invokes undefined behavior (if you dereference the pointer afterwards), because it breaks strict-aliasing. Section 3.8 of the Standard says "The lifetime of an object of type T begins when: — storage with the proper alignment and size for type T is obtained, and — if the object has non-trivial initialization, its initialization is complete." Your code only fulfills the first step. Without the second step, this memory cannot be treated as instances of std::complex<double>. – Ben Voigt Apr 29 '12 at 21:10