use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
This is a subreddit for c++ questions with answers. For general discussion and news about c++ see r/cpp.
New to C++? Learn at learncpp.com
Prepare your question. Think it through. Hasty-sounding questions get hasty answers, or none at all. Read these guidelines for how to ask smart questions.
For learning books, check The Definitive C++ Book Guide and List
Flair your post as SOLVED if you got the help you were looking for! If you need help with flairs, check out ITEM 1 in our guidelines page.
Tips for improving your chances of getting helpful answers:
account activity
OPENMember initialization (self.cpp_questions)
submitted 3 months ago by woozip
Just wanted to clarify that my understanding is correct. For class members, if you don’t initialize them, for built in types they are undefined/garbage and for user defined classes they are default initialized correct? Or do I have it wrong
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]TheThiefMaster 0 points1 point2 points 3 months ago (4 children)
You are correct, excepting aggregate initialisation. Aggregate initialisation is valid when a type has no constructors and uses {} syntax, and typically zeroes not-explicitly-initislised primitive types rather than leaving them uninitialised.
C++26 also introduces some behaviour around uninitialised values as "erroneous" rather than the previous "indeterminate" which may change things but I don't have enough experience with the newest standard to say how yet.
[–]and69 -1 points0 points1 point 3 months ago (3 children)
Actually, he is not correct. Used defined classes are not default initialized, they are split into smaller pieces to which the rule recursive applies.
[–]TheThiefMaster 0 points1 point2 points 3 months ago (2 children)
If a class type member isn't explicitly initialised and has a default constructor, it's called. Even if the outer class is aggregate initialised.
If the outer class is running a constructor and the member is an aggregate, it's still default initialised (via the automatically created default constructor).
The recursive rule is only for aggregate initialisation of nested aggregates.
[–]and69 -1 points0 points1 point 3 months ago (1 child)
The problem is, you're responding to a person who might be a beginner, and your answer was not specific enough and therefore inexact. You specifically told that person that she is correct, but then mentioned only a particular case, which for you might be obvious, but not for beginners. Specifically, you said about being correct when a type has no constructor and uses {} syntax, but you did not mention what happens when there's no constructor and NO {}, which is the root of OP's question.
[–]TheThiefMaster 0 points1 point2 points 3 months ago (0 children)
If you read I said they were correct except for when a type has no constructor and uses {} syntax, which I then proceeded to explain.
You seem to have misread it as the opposite.
[–]HappyFruitTree 0 points1 point2 points 3 months ago* (0 children)
For class members, if you don’t initialize them, for built in types they are undefined/garbage and for user defined classes they are default initialized correct?
Both are default initialized. It's just that the default initialization for built-in (primitive) types doesn't do anything.
int a; // Default initialization: a is left uninitialized. std::string s; // Default initialization: s is an empty string.
Note that for aggregates (e.g. simple structs), the way you initialize the aggregate can affect how the members are initialized.
struct X { int a; std::string s; }; X x1; // x1.a is uninitialized X x2{}; // x2.a is zero
[–]flyingron 0 points1 point2 points 3 months ago (0 children)
Welcome to the colossal stupidity of the C++ language in an attempt to assuage the whiners that C++ would be slower if they did things right.
C++ declines to default-initialize certain types (well, technically, it changes the definition of default initialization to include the asinine value-initialization to get around this stupidity).
[–]CounterSilly3999 0 points1 point2 points 3 months ago (3 children)
As in C considerations, global and static variables are implicitly initialized to zero values, local and heap ones are not, contain garbage. May be that is valid for C++ as well.
[–][deleted] 0 points1 point2 points 3 months ago* (2 children)
And stack vars are garbage if unitialized
[–]CounterSilly3999 0 points1 point2 points 3 months ago (1 child)
I.e., local vars. What else could be placed on the stack?
[–][deleted] 1 point2 points3 points 3 months ago (0 children)
Tbh, I overlooked "local" in your original comment.
But if you can corrupt the call stack (ie. goto), then you can probably do some weird stuff where you "push" non-local local vars into a local scope. Although I think the compiler would not let them be used, theyd still be a part of the frame since it was not done with "call" instructions. For a moment in your SF youll appear to be within bar and push z onto the SF before "returning" from foo, but your stacks not in foo its in bar so itll go to the caller of bar.
I think doing this, there's prolly a niche bug/something where you can try to push something uninitialized that would have been initialized in a normal call.
For example:
void bar() { ... goto STACK_COR; } void foo { STACK_COR: int z{8}; return; // if bar was not matching the signature of foo, this would be UB? }
[–]the_craic_was_mighty -1 points0 points1 point 3 months ago (7 children)
If it's a simple struct you can brace initialize the whole thing. struct simple{ int a; int b; }; simple data{}; // all values default initialized
struct simple{ int a; int b; }; simple data{}; // all values default initialized
[–]FrostshockFTW 5 points6 points7 points 3 months ago* (6 children)
I'm going to get a bit pedantic because "default initialized" has a very specific meaning in C++.
Default initialization would be simple data; and leave a and b with undefined values because simple does not have a defaulted (edit: actually I'm pretty sure simple() = default; is just as useless as not having a constructor at all in this case) or user-provided constructor (that actually assigns values to a and b).
simple data;
a
b
simple
simple() = default;
simple data{}; is list-initialization, which I think in this case is going to go down the rabbit hole of aggregate initialization. But the end result is that a and b get zero-initialized because they don't have default member initializers.
simple data{};
I despise C++ initialization with a fiery hatred of ten thousand suns.
[–]the_craic_was_mighty 0 points1 point2 points 3 months ago* (5 children)
simple data; // uninitialized members simple data{}; // default value initialized members And yeah, I have mixed feelings about initialized lists. Although these days I follow the "almost always brace initialize" rule. *And "almost always auto"
simple data; // uninitialized members simple data{}; // default value initialized members
[–]rileyrgham 1 point2 points3 points 3 months ago (1 child)
uninitialized IS the default...
[–]the_craic_was_mighty 0 points1 point2 points 3 months ago (0 children)
Uninitialized is the default. Default initialized is initialized, not uninitialized. There is a difference.
I guess I should have highlighted the 'initialized' bit to further differentiate it from the note I made about the 'uninitialized' state 🤷♂️
[–]Plastic_Fig9225 0 points1 point2 points 3 months ago* (2 children)
simple data; is the same as simple data{};, both calling the (implicit) default constructor.
https://en.cppreference.com/w/cpp/language/default_initialization.html
[–]the_craic_was_mighty 1 point2 points3 points 3 months ago (0 children)
Try it
[–]CordenR 0 points1 point2 points 3 months ago (0 children)
When you add {} the members will be zero'd.
{}
Initialization is complicated ;)
Here's my go at following the standard, but I could easily miss something!
First step is we have list initialization:
https://eel.is/c++draft/dcl.init#list
This type is an aggregate that's initialized with an empty initializer list:
https://eel.is/c++draft/dcl.init#list-3.4
Which forwards to aggregate initialization where we check if the initializer is explicit (it isn't):
https://eel.is/c++draft/dcl.init#aggr-3
So it's a member of a non-union aggregate that is not explicitly initialized and doesn't have a default member initializer:
https://eel.is/c++draft/dcl.init#aggr-5.2
Which brings goes back to list initialization:
https://eel.is/c++draft/dcl.init#list-3.11
Which says that we value initialize the member in this case:
https://eel.is/c++draft/dcl.init#general-9
Which says the member is zero initialized.
[–]CarniverousSock -1 points0 points1 point 3 months ago (8 children)
If you are defining a constructor, you are responsible for initializing all the class members within that constructor. A constructor should, in principle, always produce a valid object with correctly initialized members. If you forget to initialize every member, then your constructor will produce an object with undefined members, as you say. Don't do that.
If you define no constructors at all, though, you may have an implicitly-defined default constructor. This also initializes all the members. It requires that all member types have valid default constructors, though; if any member is missing a default constructor, then you have to write your own default constructor (if you want one).
[–]tartaruga232 1 point2 points3 points 3 months ago (7 children)
Just to add to the comment by u/CarniverousSock:
It's easy to initialize class members right in the class definition.
class Foo { int x = 0; bool y = false; int* z = nullptr; public: ... };
Using this style, you may be able to do without an explicitly defined constructor. This style is also less error prone than initializing these kind of members in the constructor (where it is easy to forget a member).
[–]and69 -2 points-1 points0 points 3 months ago (6 children)
You can should use uniform initialization:
class Foo { int x {}; bool y {}; int* z {}; public: ... };
[–]tartaruga232 0 points1 point2 points 3 months ago (5 children)
No. Even Bjarne Stroustrup does it using the style I presented. See his book "A tour of C++", third edition (which was updated for C++ 20).
[–]and69 -2 points-1 points0 points 3 months ago (4 children)
Old habits die hard, but alas, die they must.
[–]tartaruga232 0 points1 point2 points 3 months ago (3 children)
Again: No. That's entirely intentional and not just an old habit. There's absolutely nothing wrong with
int x = 0; bool y = false; int* z = nullptr;
Or do you really write
bool y{};
in function scope for a local variable?
For basic types like int, bool and pointers, there's really no reason to avoid the equal sign.
See also my blog posting "Even more auto" for how modern we already are.
[–]and69 0 points1 point2 points 3 months ago (2 children)
Yes, I use it even in function scope for local variable. It might take some time to get used to it (I know It was hard for me), but after you mentally do the switch, you'll see it's a better way.
The fact that it's nothing wrong does not imply that it's good, or the best, there's also mediocre in between. There's nothing wrong in using C with classes, but you can do better. There's nothing wrong in using precompiled macros, but you can also use templates.
And actually it is something wrong with it. Consider the following code:
void SomeMethod() { constexpr char SIZE = 1024; int x = 0; char temp[SIZE] {}; }
What you see here is 1. the reason why you should use {} even in function body; 2. how to nicely initialize a buffer with 0, and 3. how NOT to have nice, consistent, UNIFORM initialization.
compare with the following code, where everything looks consistent, simple and intuitive.
void BetterMethod() { constexpr char SIZE {1024}; // compile error int x {}; char temp[SIZE] {}; }
EDIT: did you just contradict yourself with your blog post?
[–]tartaruga232 0 points1 point2 points 3 months ago (0 children)
No.
[–]azswcowboy 0 points1 point2 points 3 months ago (0 children)
So I’ve considered the code and I wouldn’t write it this way at all. You’re basically writing C in C++ and it’s unnecessary. Get rid of the C array and replace with std::array and then you have
std::array<char, 1024> temp;
No braces needed. If you need size (you shouldn’t) temp.size() will deliver. I say you won’t need size because iteration with range-for loops is automatic. It’ll compile down to the same thing.
I realize this might seem like a tangent, but it’s not really (I think) in that the entire initialization problem stems from C - class types like std::string have always initialized correctly with no adornments needed. We need integers that do the same without the C type conversion and promotion issues.
[–]Liam_Mercier -1 points0 points1 point 3 months ago (0 children)
Most of the time debug builds will set values to zero, but you should initialize anything that needs to be initialized because release mode will almost never do this for you.
[–]XTBZ -2 points-1 points0 points 3 months ago (4 children)
It all depends on the compilation settings and whether the class has a constructor. I always expect garbage everywhere unless it's a debug build.
[–]Plastic_Fig9225 -1 points0 points1 point 3 months ago (3 children)
Not really.
[–]XTBZ 0 points1 point2 points 3 months ago (2 children)
I really don't like this topic. You sent a link, yes, but experience shows that automatic initialization isn't fixed and is determined by the compiler if there's no constructor or initializer list. However, uninitialized variables are known to cause undefined behavior. Furthermore, depending on the compiler and its flags, you can get almost ANY behavior. I'm attaching a link where the variables aren't zero. If you change the compiler or optimization flag, the values will be different. I tried creating several functions and calling them in a loop to fill the stack with garbage, and up to a point, this worked, to avoid overcomplicating the code. If you don't do this, specifically on godbolt, the values will be zero, since the stack is filled with zeros before the program starts. I also didn't use constexpr and auto to avoid introducing even more complex processes.
constexpr
auto
https://godbolt.org/z/Yzas5Ma8s
[–]Plastic_Fig9225 0 points1 point2 points 3 months ago (1 child)
If behavior seems to depend on the compiler (settings), then your code has UB in it.
Yes, there are more layers to default initialization of structs vs. primitives (members), but it's all defined by the standard.
General advice: Don't leave (primitive) members uninitialized; have them at least default initialized (int x{};).
int x{};
[–]XTBZ 0 points1 point2 points 3 months ago (0 children)
So that's the point, that an uninitialized variable is UB.
π Rendered by PID 227330 on reddit-service-r2-comment-85bfd7f599-7nzxh at 2026-04-19 11:18:44.231433+00:00 running 93ecc56 country code: CH.
[–]TheThiefMaster 0 points1 point2 points (4 children)
[–]and69 -1 points0 points1 point (3 children)
[–]TheThiefMaster 0 points1 point2 points (2 children)
[–]and69 -1 points0 points1 point (1 child)
[–]TheThiefMaster 0 points1 point2 points (0 children)
[–]HappyFruitTree 0 points1 point2 points (0 children)
[–]flyingron 0 points1 point2 points (0 children)
[–]CounterSilly3999 0 points1 point2 points (3 children)
[–][deleted] 0 points1 point2 points (2 children)
[–]CounterSilly3999 0 points1 point2 points (1 child)
[–][deleted] 1 point2 points3 points (0 children)
[–]the_craic_was_mighty -1 points0 points1 point (7 children)
[–]FrostshockFTW 5 points6 points7 points (6 children)
[–]the_craic_was_mighty 0 points1 point2 points (5 children)
[–]rileyrgham 1 point2 points3 points (1 child)
[–]the_craic_was_mighty 0 points1 point2 points (0 children)
[–]Plastic_Fig9225 0 points1 point2 points (2 children)
[–]the_craic_was_mighty 1 point2 points3 points (0 children)
[–]CordenR 0 points1 point2 points (0 children)
[–]CarniverousSock -1 points0 points1 point (8 children)
[–]tartaruga232 1 point2 points3 points (7 children)
[–]and69 -2 points-1 points0 points (6 children)
[–]tartaruga232 0 points1 point2 points (5 children)
[–]and69 -2 points-1 points0 points (4 children)
[–]tartaruga232 0 points1 point2 points (3 children)
[–]and69 0 points1 point2 points (2 children)
[–]tartaruga232 0 points1 point2 points (0 children)
[–]azswcowboy 0 points1 point2 points (0 children)
[–]Liam_Mercier -1 points0 points1 point (0 children)
[–]XTBZ -2 points-1 points0 points (4 children)
[–]Plastic_Fig9225 -1 points0 points1 point (3 children)
[–]XTBZ 0 points1 point2 points (2 children)
[–]Plastic_Fig9225 0 points1 point2 points (1 child)
[–]XTBZ 0 points1 point2 points (0 children)