> [...] The printed result would be 0. This is because we value-initialize t and, since T has a non-user-provided default constructor, the object is zero-initialized (hence t.x is zero-initialized) then default-initialized (calling the implicitly-defined default constructor, which does nothing).<p>T̶h̶a̶t̶ d̶o̶e̶s̶n̶'t̶ s̶e̶e̶m̶ c̶o̶r̶r̶e̶c̶t̶:̶ a̶ d̶e̶f̶a̶u̶l̶t̶e̶d̶ c̶o̶n̶s̶t̶r̶u̶c̶t̶o̶r̶ s̶t̶i̶l̶l̶ d̶e̶f̶a̶u̶l̶t̶-̶i̶n̶i̶t̶i̶a̶l̶i̶z̶e̶s̶ t̶h̶e̶ m̶e̶m̶b̶e̶r̶s̶, n̶o̶t̶ v̶a̶l̶u̶e̶ i̶n̶i̶t̶i̶a̶l̶i̶z̶e̶. I̶ d̶o̶n̶'t̶ t̶h̶i̶n̶k̶ t̶h̶e̶r̶e̶ i̶s̶ a̶n̶y̶ d̶i̶f̶f̶e̶r̶e̶n̶c̶e̶ b̶e̶t̶w̶e̶e̶n̶ d̶e̶f̶a̶u̶l̶t̶i̶n̶g̶ i̶n̶l̶i̶n̶e̶ a̶n̶d̶ o̶u̶t̶ o̶f̶ l̶i̶n̶e̶. G̶C̶C̶ s̶e̶e̶m̶s̶ t̶o̶ a̶g̶r̶e̶e̶:̶ h̶t̶t̶p̶s̶:̶//g̶c̶c̶.g̶o̶d̶b̶o̶l̶t̶.o̶r̶g̶/z̶/r̶4̶r̶e̶5̶T̶E̶5̶a̶<p>edit: I missed that the author is actually value-initializing x!!! The result definitely violates expectations!<p>Generally, the details of the rules are arcane and sometimes have non-sensical dark corners having been extended and patched up for the last 40 years. But 99.9%[1] of the time you get what you expect.<p>I big improvement would be making default initialization explicit, and otherwise always value initialize. Explicit value initialization is so common that the very rare times I want default initialization (to avoid expensively zeroing large arrays) I need to write a fat comment. Writing "std::array<int, 100> = void;" (or whatever the syntax would be) would be much better.<p>[1] I had an extra 9 here... I hedged.
The whole thing is wrong. Don’t put const references in your structs. Use std::reference_wrapper if you must.<p>Edit: this response is a bit dismissive but honestly my main beef with this article is that its conclusion is just straight up wrong. Do not write your own constructors, do follow the rule of 5/3/0, and if you find yourself needing to hold a const reference, you should look out for whether you’re passing in an rval temporary… none of this is really scary.
>I Have No Mouth, and I Must Scream (1967)<p><a href="https://talesofmytery.blogspot.com/2018/10/harlan-ellison-i-have-no-mouth-and-i.html" rel="nofollow">https://talesofmytery.blogspot.com/2018/10/harlan-ellison-i-...</a>
I’m surprised there were no snarky comments about:<p>> So, here’s the glue between list-initialization and aggregate initialization: if list-initialization is performed on an aggregate, aggregate initialization is performed <i>unless</i> the list has only one argument, of type T or of type derived from T, in which case it performs direct-initialization (or copy-initialization).<p>The word “unless” is even bold.<p>We have fancy syntax:<p><pre><code> T t{v0};
</code></pre>
And we also have:<p><pre><code> T t{v0, v1};
</code></pre>
And so on. But the one-element case does not reliably work like the 2+-element case. And this is in a language that increasingly works toward making it straightforward to create a struct from a parameter pack and has support for variable length array-ish things that one can initialize like this. And the types can, of course, be templated.<p>So you can write your own constructors, and you can initialize a tuple or array with only one element supplied, and you might trip over the <i>wrong</i> constructor being invoked in special cases.<p>I remember discovering this when C++11 initializer lists were brand new and thinking it was nuts.
For more C++ wackiness, I recommend the C++ FQA: <a href="https://yosefk.com/c++fqa/" rel="nofollow">https://yosefk.com/c++fqa/</a><p>It's 15 years out of date now, but also timeless since C++ rarely/never removes old features or behaviours.
Horrific. One of the things that scares me about C++. A real shame because it has some cool features and some brilliant minds working on it.<p>I'm hoping something like Herb's C++ syntax 2 will make the language useable for mortals like me.
Man I get vertigo reading this. Reminds me of trying to understand Java constructors and object initialisation.<p>It’s been a while now, and at least in my experience so far Go and Rusts choice of not having special constructors really simplifies a lot.<p>Is there anyone that’s had the experience of missing constructors once you swapped away from them?
Is there a C++ tool that adds/shows all the implicit stuff that happens behind the scenes?<p>Such as all the constructors that are being added, implicit copy constructor and all the other surprises?
<p><pre><code> T::T() = default;
</code></pre>
> You’d expect the printed result to be 0, right? You poor thing. Alas—it will be garbage. Some things can never be perfect, it seems. Here’s a relevant excerpt from our description of value-initialization:<p>Link: <a href="https://consteval.ca/2024/07/03/initialization/#:~:text=You%E2%80%99d%20expect%20the%20printed%20result%20to%20be%200%2C%20right%3F%20You%20poor%20thing.%20Alas%E2%80%94it%20will%20be%20garbage.%20Some%20things%20can%20never%20be%20perfect%2C%20it%20seems.%20Here%E2%80%99s%20a%20relevant%20excerpt%20from%20our%20description%20of%20value%2Dinitialization%3A" rel="nofollow">https://consteval.ca/2024/07/03/initialization/#:~:text=You%...</a><p>That actually isn't that weird, because it would allow any consumer of your library to change how your library behaves.
After almost 20 years of experience with C++, there are still some gnarly details I wouldn't have imagined. What a God awful language!<p>Kudos to that author for the great, eye catching title and the in depth detail!
A language shouldn't be this complicated. This is dangerous and impossible for teams full of juniors and busy people with deadlines. We're only human.
> <i>Otherwise, zero-initialize and then default-initialize.</i><p>That can't be right ... is it? Things cannot be initialized twice. Isn't it more like "Otherwise, recurse the value-initialization over the bases and members". Then, those that are not classes or arrays get zero-initialized.
Realizing the spec for C++23 is about two-and-some-change-times the length of the King James Bible has really reframed my thinking on this language.<p>For good or for ill, I don't really trust <i>anything</i> that long to be something the average human can wrestle down. And when you mix in undefined behavior and the fact it's still used on safety-critical systems... It's a bit horrifying really.
The article is just plain wrong about classes: if you have declared any constructor, then the language will <i>not</i> provide a default constructor and default-initialization will fail with a compiler diagnostic.<p>So their claim that "T t;" will "do nothing" is incorrect.<p><pre><code> class T
{
public:
T(int);
};
T t;
</code></pre>
Will fail.
I agree there is a lot of complexity in C++ in the year 2024, however I feel that much of the appearance of complexity around initialization is due to the pedantic, dogmatic use of the word "default" by the committee to mean "not".
I'm so glad I use Go more than C++ these days. In Go, all values are always zero-initialized if you don't explicitly assign a value. If you need a constructor, you write a regular function that returns an explicitly assigned object.<p>I like keeping the rules of the language simple enough that there is never any confusion.