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 articleThis 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
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
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
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++
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
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.
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.
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.
https://talesofmytery.blogspot.com/2018/10/harlan-ellison-i-...
> 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.
It's 15 years out of date now, but also timeless since C++ rarely/never removes old features or behaviours.
I'm hoping something like Herb's C++ syntax 2 will make the language useable for mortals like me.
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?
Such as all the constructors that are being added, implicit copy constructor and all the other surprises?
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.
Kudos to that author for the great, eye catching title and the in depth detail!
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.
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.
So their claim that "T t;" will "do nothing" is incorrect.
class T
{
public:
T(int);
};
T t;
Will fail.I like keeping the rules of the language simple enough that there is never any confusion.
"Call J. G. Wentworth, 877 Cash Now!"
Related
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
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
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++
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
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.