July 5th, 2024

I Have No Constructor, and I Must Initialize

This article explores C++ initialization intricacies, covering constructors, default and value initialization, user-provided constructors' impact, aggregates, list-initialization types, and narrowing conversions, offering a comprehensive view of object initialization.

Read original articleLink Icon
I Have No Constructor, and I Must Initialize

This article delves into the intricacies of initialization in C++, focusing on constructors and initialization rules. It discusses default-initialization and value-initialization for different types, highlighting scenarios where objects may be left uninitialized. The text explains the implications of user-provided constructors on default initialization and delves into the concept of aggregates and aggregate initialization. It clarifies the differences between list-initialization, direct-list-initialization, and copy-list-initialization, emphasizing their roles in initializing objects. The article also touches on the use of parentheses versus braces for initialization purposes and the considerations around narrowing conversions in list-initialization. Overall, it provides a detailed exploration of C++ initialization mechanisms and their implications on object construction and initialization outcomes.

Related

How the STL Uses Explicit

How the STL Uses Explicit

The WG21 meeting in St. Louis discusses a paper on using the `explicit` keyword in C++ proposals to establish a style guide for consistency. Guidelines differ between industry and Standard Library practices.

Weekend projects: getting silly with C

Weekend projects: getting silly with C

The C programming language's simplicity and expressiveness, despite quirks, influence other languages. Unconventional code structures showcase creativity and flexibility, promoting unique coding practices. Subscription for related content is encouraged.

The Byte Order Fiasco

The Byte Order Fiasco

Handling endianness in C/C++ programming poses challenges, emphasizing correct integer deserialization to prevent undefined behavior. Adherence to the C standard is crucial to avoid unexpected compiler optimizations. Code examples demonstrate proper deserialization techniques using masking and shifting for system compatibility. Mastery of these concepts is vital for robust C code, despite available APIs for byte swapping.

I _____ hate arrays in C++

I _____ hate arrays in C++

The article explores challenges in using arrays in C++, focusing on array-to-pointer conversion pitfalls, differences from pointers, and practical examples of errors. Caution and awareness are advised for C++ developers.

A Type for Overload Set

A Type for Overload Set

The article explores C++ overload set challenges, discussing issues with standard functions encountering problems due to overloading. It introduces proposal P3312 for a unique type to address these limitations, emphasizing the need for a more efficient solution.

Link Icon 25 comments
By @gpderetta - 3 months
> [...] 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).

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̶

edit: I missed that the author is actually value-initializing x!!! The result definitely violates expectations!

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.

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.

[1] I had an extra 9 here... I hedged.

By @nickysielicki - 3 months
The whole thing is wrong. Don’t put const references in your structs. Use std::reference_wrapper if you must.

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.

By @bookofjoe - 3 months
>I Have No Mouth, and I Must Scream (1967)

https://talesofmytery.blogspot.com/2018/10/harlan-ellison-i-...

By @amluto - 3 months
I’m surprised there were no snarky comments about:

> So, here’s the glue between list-initialization and aggregate initialization: if list-initialization is performed on an aggregate, aggregate initialization is performed unless 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).

The word “unless” is even bold.

We have fancy syntax:

    T t{v0};
And we also have:

    T t{v0, v1};
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.

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 wrong constructor being invoked in special cases.

I remember discovering this when C++11 initializer lists were brand new and thinking it was nuts.

By @AlexandrB - 3 months
For more C++ wackiness, I recommend the C++ FQA: https://yosefk.com/c++fqa/

It's 15 years out of date now, but also timeless since C++ rarely/never removes old features or behaviours.

By @gattilorenz - 3 months
What an beautiful blog theme, obviously inspired by the DEC-era computers but also clean and minimal. Refreshing!
By @IAmLiterallyAB - 3 months
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.

I'm hoping something like Herb's C++ syntax 2 will make the language useable for mortals like me.

By @jakewins - 3 months
Man I get vertigo reading this. Reminds me of trying to understand Java constructors and object initialisation.

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.

Is there anyone that’s had the experience of missing constructors once you swapped away from them?

By @jolj - 3 months
Is there a C++ tool that adds/shows all the implicit stuff that happens behind the scenes?

Such as all the constructors that are being added, implicit copy constructor and all the other surprises?

By @OptionOfT - 3 months

    T::T() = default;
> 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:

Link: https://consteval.ca/2024/07/03/initialization/#:~:text=You%...

That actually isn't that weird, because it would allow any consumer of your library to change how your library behaves.

By @marton78 - 3 months
After almost 20 years of experience with C++, there are still some gnarly details I wouldn't have imagined. What a God awful language!

Kudos to that author for the great, eye catching title and the in depth detail!

By @echelon - 3 months
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.
By @kazinator - 3 months
> Otherwise, zero-initialize and then default-initialize.

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.

By @shadowgovt - 3 months
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.

For good or for ill, I don't really trust anything 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.

By @wateralien - 3 months
Upvote for the title.
By @pierrebai - 3 months
The article is just plain wrong about classes: if you have declared any constructor, then the language will not provide a default constructor and default-initialization will fail with a compiler diagnostic.

So their claim that "T t;" will "do nothing" is incorrect.

    class T
    {
    public:
        T(int);
    };
    T t;
Will fail.
By @jeffbee - 3 months
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".
By @hwc - 3 months
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.

I like keeping the rules of the language simple enough that there is never any confusion.

By @MathMonkeyMan - 3 months
Show me someone who understands the rules, and I'll show you a compiler engineer... who probably doesn't understand the rules.
By @sixtram - 3 months
Great link, I'm going to add this to my list of favorite interview questions. (^_-)
By @nxobject - 3 months
As an aside, I see that DEC front panel you've got there in your blog header.
By @vsgherzi - 3 months
this has got to be one of my favorite blog names i've seen on this site
By @gnarlouse - 3 months
this title makes me want to shout

"Call J. G. Wentworth, 877 Cash Now!"

By @3l3ktr4 - 3 months
This is the best title, OP.