C++ zero initialization - Why is `b` in this program uninitialized, but `a` is initialized?
According to the accepted (and only) answer for this Stack Overflow question,
Defining the constructor with
MyTest() = default;
will instead zero-initialize the object.
Then why does the following,
#include <iostream>
struct foo {
foo() = default;
int a;
};
struct bar {
bar();
int b;
};
bar::bar() = default;
int main() {
foo a{};
bar b{};
std::cout << a.a << ' ' << b.b;
}
produce this output:
0 32766
Both constructors defined are default? Right? And for POD types, the default initialization is zero-initialization.
And according to the accepted answer for this question,
If a POD member is not initialized in the constructor nor via C++11
in-class initialization, it is default-initialized.
The answer is the same regardless of stack or heap.
In C++98 (and not afterward), new int() was specified as performing
zero initialization.
Despite trying to wrap my (albeit tiny) head around default constructors and default initialization, I couldn't come up with an explanation.
c++ initialization language-lawyer
|
show 13 more comments
According to the accepted (and only) answer for this Stack Overflow question,
Defining the constructor with
MyTest() = default;
will instead zero-initialize the object.
Then why does the following,
#include <iostream>
struct foo {
foo() = default;
int a;
};
struct bar {
bar();
int b;
};
bar::bar() = default;
int main() {
foo a{};
bar b{};
std::cout << a.a << ' ' << b.b;
}
produce this output:
0 32766
Both constructors defined are default? Right? And for POD types, the default initialization is zero-initialization.
And according to the accepted answer for this question,
If a POD member is not initialized in the constructor nor via C++11
in-class initialization, it is default-initialized.
The answer is the same regardless of stack or heap.
In C++98 (and not afterward), new int() was specified as performing
zero initialization.
Despite trying to wrap my (albeit tiny) head around default constructors and default initialization, I couldn't come up with an explanation.
c++ initialization language-lawyer
3
Interestingly, I even get a warning for b: main.cpp:18:34: warning: 'b.bar::b' is used uninitialized in this function [-Wuninitialized] coliru.stacked-crooked.com/a/d1b08a4d6fb4ca7e
– tkausl
11 hours ago
1
@TheQuantumPhysicist, for that I ran the program maybe 5~6 times before posting and about 10 times now,a
is always zero.b
changes around a little.
– Joey Mallone
11 hours ago
5
bar
's constructor is user provided whereasfoo
's constructor is the defaulted one.
– Jarod42
11 hours ago
2
@PeteBecker, I understand that. How could I somehow shake my RAM a little so that if there was zero there, it should now be something else. ;) p.s. I ran the program a dozen times. It is not a big program. You could run it and test it on your system.a
is zero.b
is not. Seemsa
is initialized.
– Joey Mallone
11 hours ago
1
@JoeyMallone Regarding "how is it user-provided": There is no guarantee that the definition ofbar::bar()
is visible inmain()
- it might be defined in a separate compilation unit and do something very non-trivial while inmain()
only the declaration is visible. I think you'll agree that this behavior shouldn't change depending on whether you placebar::bar()
's definition in a separate compilation unit or not (even if the whole situation is unintuitive).
– Max Langhof
11 hours ago
|
show 13 more comments
According to the accepted (and only) answer for this Stack Overflow question,
Defining the constructor with
MyTest() = default;
will instead zero-initialize the object.
Then why does the following,
#include <iostream>
struct foo {
foo() = default;
int a;
};
struct bar {
bar();
int b;
};
bar::bar() = default;
int main() {
foo a{};
bar b{};
std::cout << a.a << ' ' << b.b;
}
produce this output:
0 32766
Both constructors defined are default? Right? And for POD types, the default initialization is zero-initialization.
And according to the accepted answer for this question,
If a POD member is not initialized in the constructor nor via C++11
in-class initialization, it is default-initialized.
The answer is the same regardless of stack or heap.
In C++98 (and not afterward), new int() was specified as performing
zero initialization.
Despite trying to wrap my (albeit tiny) head around default constructors and default initialization, I couldn't come up with an explanation.
c++ initialization language-lawyer
According to the accepted (and only) answer for this Stack Overflow question,
Defining the constructor with
MyTest() = default;
will instead zero-initialize the object.
Then why does the following,
#include <iostream>
struct foo {
foo() = default;
int a;
};
struct bar {
bar();
int b;
};
bar::bar() = default;
int main() {
foo a{};
bar b{};
std::cout << a.a << ' ' << b.b;
}
produce this output:
0 32766
Both constructors defined are default? Right? And for POD types, the default initialization is zero-initialization.
And according to the accepted answer for this question,
If a POD member is not initialized in the constructor nor via C++11
in-class initialization, it is default-initialized.
The answer is the same regardless of stack or heap.
In C++98 (and not afterward), new int() was specified as performing
zero initialization.
Despite trying to wrap my (albeit tiny) head around default constructors and default initialization, I couldn't come up with an explanation.
c++ initialization language-lawyer
c++ initialization language-lawyer
edited 3 hours ago
Boann
36.8k1289121
36.8k1289121
asked 11 hours ago
Joey MalloneJoey Mallone
1,32721326
1,32721326
3
Interestingly, I even get a warning for b: main.cpp:18:34: warning: 'b.bar::b' is used uninitialized in this function [-Wuninitialized] coliru.stacked-crooked.com/a/d1b08a4d6fb4ca7e
– tkausl
11 hours ago
1
@TheQuantumPhysicist, for that I ran the program maybe 5~6 times before posting and about 10 times now,a
is always zero.b
changes around a little.
– Joey Mallone
11 hours ago
5
bar
's constructor is user provided whereasfoo
's constructor is the defaulted one.
– Jarod42
11 hours ago
2
@PeteBecker, I understand that. How could I somehow shake my RAM a little so that if there was zero there, it should now be something else. ;) p.s. I ran the program a dozen times. It is not a big program. You could run it and test it on your system.a
is zero.b
is not. Seemsa
is initialized.
– Joey Mallone
11 hours ago
1
@JoeyMallone Regarding "how is it user-provided": There is no guarantee that the definition ofbar::bar()
is visible inmain()
- it might be defined in a separate compilation unit and do something very non-trivial while inmain()
only the declaration is visible. I think you'll agree that this behavior shouldn't change depending on whether you placebar::bar()
's definition in a separate compilation unit or not (even if the whole situation is unintuitive).
– Max Langhof
11 hours ago
|
show 13 more comments
3
Interestingly, I even get a warning for b: main.cpp:18:34: warning: 'b.bar::b' is used uninitialized in this function [-Wuninitialized] coliru.stacked-crooked.com/a/d1b08a4d6fb4ca7e
– tkausl
11 hours ago
1
@TheQuantumPhysicist, for that I ran the program maybe 5~6 times before posting and about 10 times now,a
is always zero.b
changes around a little.
– Joey Mallone
11 hours ago
5
bar
's constructor is user provided whereasfoo
's constructor is the defaulted one.
– Jarod42
11 hours ago
2
@PeteBecker, I understand that. How could I somehow shake my RAM a little so that if there was zero there, it should now be something else. ;) p.s. I ran the program a dozen times. It is not a big program. You could run it and test it on your system.a
is zero.b
is not. Seemsa
is initialized.
– Joey Mallone
11 hours ago
1
@JoeyMallone Regarding "how is it user-provided": There is no guarantee that the definition ofbar::bar()
is visible inmain()
- it might be defined in a separate compilation unit and do something very non-trivial while inmain()
only the declaration is visible. I think you'll agree that this behavior shouldn't change depending on whether you placebar::bar()
's definition in a separate compilation unit or not (even if the whole situation is unintuitive).
– Max Langhof
11 hours ago
3
3
Interestingly, I even get a warning for b: main.cpp:18:34: warning: 'b.bar::b' is used uninitialized in this function [-Wuninitialized] coliru.stacked-crooked.com/a/d1b08a4d6fb4ca7e
– tkausl
11 hours ago
Interestingly, I even get a warning for b: main.cpp:18:34: warning: 'b.bar::b' is used uninitialized in this function [-Wuninitialized] coliru.stacked-crooked.com/a/d1b08a4d6fb4ca7e
– tkausl
11 hours ago
1
1
@TheQuantumPhysicist, for that I ran the program maybe 5~6 times before posting and about 10 times now,
a
is always zero. b
changes around a little.– Joey Mallone
11 hours ago
@TheQuantumPhysicist, for that I ran the program maybe 5~6 times before posting and about 10 times now,
a
is always zero. b
changes around a little.– Joey Mallone
11 hours ago
5
5
bar
's constructor is user provided whereas foo
's constructor is the defaulted one.– Jarod42
11 hours ago
bar
's constructor is user provided whereas foo
's constructor is the defaulted one.– Jarod42
11 hours ago
2
2
@PeteBecker, I understand that. How could I somehow shake my RAM a little so that if there was zero there, it should now be something else. ;) p.s. I ran the program a dozen times. It is not a big program. You could run it and test it on your system.
a
is zero. b
is not. Seems a
is initialized.– Joey Mallone
11 hours ago
@PeteBecker, I understand that. How could I somehow shake my RAM a little so that if there was zero there, it should now be something else. ;) p.s. I ran the program a dozen times. It is not a big program. You could run it and test it on your system.
a
is zero. b
is not. Seems a
is initialized.– Joey Mallone
11 hours ago
1
1
@JoeyMallone Regarding "how is it user-provided": There is no guarantee that the definition of
bar::bar()
is visible in main()
- it might be defined in a separate compilation unit and do something very non-trivial while in main()
only the declaration is visible. I think you'll agree that this behavior shouldn't change depending on whether you place bar::bar()
's definition in a separate compilation unit or not (even if the whole situation is unintuitive).– Max Langhof
11 hours ago
@JoeyMallone Regarding "how is it user-provided": There is no guarantee that the definition of
bar::bar()
is visible in main()
- it might be defined in a separate compilation unit and do something very non-trivial while in main()
only the declaration is visible. I think you'll agree that this behavior shouldn't change depending on whether you place bar::bar()
's definition in a separate compilation unit or not (even if the whole situation is unintuitive).– Max Langhof
11 hours ago
|
show 13 more comments
3 Answers
3
active
oldest
votes
The issue here is pretty subtle. You would think that
bar::bar() = default;
would give you a compiler generated default constructor, and it does, but it is now considered user provided. [dcl.fct.def.default]/5 states:
Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor] [class.dtor], [class.copy.ctor], [class.copy.assign]), which might mean defining them as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]
emphasis mine
So we can see that since you did not default bar()
when you first declared it, it is now considered user provided. Because of that [dcl.init]/8.2
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
no longer applies and we are not value initializing b
but instead default initializing it per [dcl.init]/8.1
if T is a (possibly cv-qualified) class type ([class]) with either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
16
I mean(*_*)
.... If to even use the basic constructs of the language, I need to read the fine print of the language draft, then Hallelujah! But it probably seems to be what you say.
– Joey Mallone
11 hours ago
5
@balki Yes, doingbar::bar() = default
out of line is the same as doingbar::bar(){}
inline.
– NathanOliver
11 hours ago
5
@JoeyMallone Yeah, C++ can be pretty complicated. I'm not sure what the reason for this is.
– NathanOliver
11 hours ago
3
If there is a previous declaration, then a subsequent definition with the default keyword will NOT zero initialize the members. Right? This is correct. It is what is happening here.
– NathanOliver
10 hours ago
3
The reason is right there in your quote: the point of an out-of-line default is to "provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base", in other words, enable you to switch to a user-written body later if necessary without breaking ABI. Note that the out-of-line definition is not implicitly inline and so can only appear in one TU by default; another TU seeing the class definition alone has no way to know if it's explicitly defined as defaulted.
– T.C.
6 hours ago
|
show 7 more comments
The difference in behaviour comes from the fact that, according to [dcl.fct.def.default]/5
, bar::bar
is user-provided where foo::foo
is not1. As a consequence, foo::foo
will value-initialize its members (meaning: zero-initialize foo::a
) but bar::bar
will stay uninitialized2.
1)[dcl.fct.def.default]/5
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
2)
From [dcl.init#6]:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
...
From [dcl.init.list]:
List-initialization of an object or reference of type T is defined as follows:
...
Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
From Vittorio Romeo's answer
add a comment |
From cppreference:
Aggregate initialization initializes aggregates. It is a form of list-initialization.
An aggregate is one of the following types:
[snip]
class type [snip], that has
[snip] (there are variations for different standard versions)
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
[snip] (there are more rules, which apply to both classes)
Given this definition, foo
is an aggregate, while bar
is not (it has user-provided, non-defaulted constructor).
Therefore for foo
, T object {arg1, arg2, ...};
is syntax for aggregate initialisation.
The effects of aggregate initialization are:
[snip] (some details irrelevant to this case)
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized.
Therefore a.a
is value initialised, which for int
means zero initialisation.
For bar
, T object {};
on the other hand is value initialisation (of the class instance, not value initialisation of members!). Since it is a class type with a default constructor, the default constructor is called. The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int
(with non-static storage) leaves b.b
with an indeterminate value.
And for pod-types, the default initialization is zero-initialization.
No. This is wrong.
P.S. A word about your experiment and your conclusion: Seeing that output is zero does not necessarily mean that the variable was zero initialised. Zero is perfectly possible number for a garbage value.
for that I ran the program maybe 5~6 times before posting and about 10 times now, a is always zero. b changes around a little.
The fact that the value was same multiple times does not necessarily mean that it was initialised either.
I also tried with set(CMAKE_CXX_STANDARD 14). The result was the same.
The fact that result is the same with multiple compiler options doesn't mean that the variable is initialised. (Although in some cases, changing standard version can change whether it is initialised).
How could I somehow shake my RAM a little so that if there was zero there, it should now be something else
There is no guaranteed way in C++ to make uninitialised value value to appear nonzero.
Only way to know that a variable is initialised is to compare program to the rules of the language and verify that the rules say that it is initialised. In this case a.a
is indeed initialised.
"The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int leaves it with an indeterminate value." --> eh! "for pod-types, the default initialization is zero-initialization." or am I wrong?
– Joey Mallone
11 hours ago
2
@JoeyMallone Default initialization of POD types is no initialization.
– NathanOliver
11 hours ago
@NathanOliver, Then I am even more confused. Then how comea
is initialized. I was thinkinga
is default initialized and default initialization for a member POD is, zero-initialization. Isa
then just luckily always coming up zero, no matter how many times I run this program.
– Joey Mallone
10 hours ago
@JoeyMalloneThen how come a is initialized.
Because it is value initialised.I was thinking a is default initialized
It is not.
– eerorika
10 hours ago
3
@JoeyMallone Don't worry about it. You could make a book out of initialization in C++. If you get a chance CppCon on youtube has a few videos on initialization with the most disappointing (as in pointing out how bad it is) being youtube.com/watch?v=7DTlWPgX6zs
– NathanOliver
10 hours ago
|
show 3 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54350114%2fc-zero-initialization-why-is-b-in-this-program-uninitialized-but-a-is-i%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
The issue here is pretty subtle. You would think that
bar::bar() = default;
would give you a compiler generated default constructor, and it does, but it is now considered user provided. [dcl.fct.def.default]/5 states:
Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor] [class.dtor], [class.copy.ctor], [class.copy.assign]), which might mean defining them as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]
emphasis mine
So we can see that since you did not default bar()
when you first declared it, it is now considered user provided. Because of that [dcl.init]/8.2
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
no longer applies and we are not value initializing b
but instead default initializing it per [dcl.init]/8.1
if T is a (possibly cv-qualified) class type ([class]) with either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
16
I mean(*_*)
.... If to even use the basic constructs of the language, I need to read the fine print of the language draft, then Hallelujah! But it probably seems to be what you say.
– Joey Mallone
11 hours ago
5
@balki Yes, doingbar::bar() = default
out of line is the same as doingbar::bar(){}
inline.
– NathanOliver
11 hours ago
5
@JoeyMallone Yeah, C++ can be pretty complicated. I'm not sure what the reason for this is.
– NathanOliver
11 hours ago
3
If there is a previous declaration, then a subsequent definition with the default keyword will NOT zero initialize the members. Right? This is correct. It is what is happening here.
– NathanOliver
10 hours ago
3
The reason is right there in your quote: the point of an out-of-line default is to "provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base", in other words, enable you to switch to a user-written body later if necessary without breaking ABI. Note that the out-of-line definition is not implicitly inline and so can only appear in one TU by default; another TU seeing the class definition alone has no way to know if it's explicitly defined as defaulted.
– T.C.
6 hours ago
|
show 7 more comments
The issue here is pretty subtle. You would think that
bar::bar() = default;
would give you a compiler generated default constructor, and it does, but it is now considered user provided. [dcl.fct.def.default]/5 states:
Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor] [class.dtor], [class.copy.ctor], [class.copy.assign]), which might mean defining them as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]
emphasis mine
So we can see that since you did not default bar()
when you first declared it, it is now considered user provided. Because of that [dcl.init]/8.2
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
no longer applies and we are not value initializing b
but instead default initializing it per [dcl.init]/8.1
if T is a (possibly cv-qualified) class type ([class]) with either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
16
I mean(*_*)
.... If to even use the basic constructs of the language, I need to read the fine print of the language draft, then Hallelujah! But it probably seems to be what you say.
– Joey Mallone
11 hours ago
5
@balki Yes, doingbar::bar() = default
out of line is the same as doingbar::bar(){}
inline.
– NathanOliver
11 hours ago
5
@JoeyMallone Yeah, C++ can be pretty complicated. I'm not sure what the reason for this is.
– NathanOliver
11 hours ago
3
If there is a previous declaration, then a subsequent definition with the default keyword will NOT zero initialize the members. Right? This is correct. It is what is happening here.
– NathanOliver
10 hours ago
3
The reason is right there in your quote: the point of an out-of-line default is to "provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base", in other words, enable you to switch to a user-written body later if necessary without breaking ABI. Note that the out-of-line definition is not implicitly inline and so can only appear in one TU by default; another TU seeing the class definition alone has no way to know if it's explicitly defined as defaulted.
– T.C.
6 hours ago
|
show 7 more comments
The issue here is pretty subtle. You would think that
bar::bar() = default;
would give you a compiler generated default constructor, and it does, but it is now considered user provided. [dcl.fct.def.default]/5 states:
Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor] [class.dtor], [class.copy.ctor], [class.copy.assign]), which might mean defining them as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]
emphasis mine
So we can see that since you did not default bar()
when you first declared it, it is now considered user provided. Because of that [dcl.init]/8.2
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
no longer applies and we are not value initializing b
but instead default initializing it per [dcl.init]/8.1
if T is a (possibly cv-qualified) class type ([class]) with either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
The issue here is pretty subtle. You would think that
bar::bar() = default;
would give you a compiler generated default constructor, and it does, but it is now considered user provided. [dcl.fct.def.default]/5 states:
Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor] [class.dtor], [class.copy.ctor], [class.copy.assign]), which might mean defining them as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [ Note: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note ]
emphasis mine
So we can see that since you did not default bar()
when you first declared it, it is now considered user provided. Because of that [dcl.init]/8.2
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
no longer applies and we are not value initializing b
but instead default initializing it per [dcl.init]/8.1
if T is a (possibly cv-qualified) class type ([class]) with either no default constructor ([class.default.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
edited 11 hours ago
answered 11 hours ago
NathanOliverNathanOliver
89.9k15125190
89.9k15125190
16
I mean(*_*)
.... If to even use the basic constructs of the language, I need to read the fine print of the language draft, then Hallelujah! But it probably seems to be what you say.
– Joey Mallone
11 hours ago
5
@balki Yes, doingbar::bar() = default
out of line is the same as doingbar::bar(){}
inline.
– NathanOliver
11 hours ago
5
@JoeyMallone Yeah, C++ can be pretty complicated. I'm not sure what the reason for this is.
– NathanOliver
11 hours ago
3
If there is a previous declaration, then a subsequent definition with the default keyword will NOT zero initialize the members. Right? This is correct. It is what is happening here.
– NathanOliver
10 hours ago
3
The reason is right there in your quote: the point of an out-of-line default is to "provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base", in other words, enable you to switch to a user-written body later if necessary without breaking ABI. Note that the out-of-line definition is not implicitly inline and so can only appear in one TU by default; another TU seeing the class definition alone has no way to know if it's explicitly defined as defaulted.
– T.C.
6 hours ago
|
show 7 more comments
16
I mean(*_*)
.... If to even use the basic constructs of the language, I need to read the fine print of the language draft, then Hallelujah! But it probably seems to be what you say.
– Joey Mallone
11 hours ago
5
@balki Yes, doingbar::bar() = default
out of line is the same as doingbar::bar(){}
inline.
– NathanOliver
11 hours ago
5
@JoeyMallone Yeah, C++ can be pretty complicated. I'm not sure what the reason for this is.
– NathanOliver
11 hours ago
3
If there is a previous declaration, then a subsequent definition with the default keyword will NOT zero initialize the members. Right? This is correct. It is what is happening here.
– NathanOliver
10 hours ago
3
The reason is right there in your quote: the point of an out-of-line default is to "provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base", in other words, enable you to switch to a user-written body later if necessary without breaking ABI. Note that the out-of-line definition is not implicitly inline and so can only appear in one TU by default; another TU seeing the class definition alone has no way to know if it's explicitly defined as defaulted.
– T.C.
6 hours ago
16
16
I mean
(*_*)
.... If to even use the basic constructs of the language, I need to read the fine print of the language draft, then Hallelujah! But it probably seems to be what you say.– Joey Mallone
11 hours ago
I mean
(*_*)
.... If to even use the basic constructs of the language, I need to read the fine print of the language draft, then Hallelujah! But it probably seems to be what you say.– Joey Mallone
11 hours ago
5
5
@balki Yes, doing
bar::bar() = default
out of line is the same as doing bar::bar(){}
inline.– NathanOliver
11 hours ago
@balki Yes, doing
bar::bar() = default
out of line is the same as doing bar::bar(){}
inline.– NathanOliver
11 hours ago
5
5
@JoeyMallone Yeah, C++ can be pretty complicated. I'm not sure what the reason for this is.
– NathanOliver
11 hours ago
@JoeyMallone Yeah, C++ can be pretty complicated. I'm not sure what the reason for this is.
– NathanOliver
11 hours ago
3
3
If there is a previous declaration, then a subsequent definition with the default keyword will NOT zero initialize the members. Right? This is correct. It is what is happening here.
– NathanOliver
10 hours ago
If there is a previous declaration, then a subsequent definition with the default keyword will NOT zero initialize the members. Right? This is correct. It is what is happening here.
– NathanOliver
10 hours ago
3
3
The reason is right there in your quote: the point of an out-of-line default is to "provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base", in other words, enable you to switch to a user-written body later if necessary without breaking ABI. Note that the out-of-line definition is not implicitly inline and so can only appear in one TU by default; another TU seeing the class definition alone has no way to know if it's explicitly defined as defaulted.
– T.C.
6 hours ago
The reason is right there in your quote: the point of an out-of-line default is to "provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base", in other words, enable you to switch to a user-written body later if necessary without breaking ABI. Note that the out-of-line definition is not implicitly inline and so can only appear in one TU by default; another TU seeing the class definition alone has no way to know if it's explicitly defined as defaulted.
– T.C.
6 hours ago
|
show 7 more comments
The difference in behaviour comes from the fact that, according to [dcl.fct.def.default]/5
, bar::bar
is user-provided where foo::foo
is not1. As a consequence, foo::foo
will value-initialize its members (meaning: zero-initialize foo::a
) but bar::bar
will stay uninitialized2.
1)[dcl.fct.def.default]/5
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
2)
From [dcl.init#6]:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
...
From [dcl.init.list]:
List-initialization of an object or reference of type T is defined as follows:
...
Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
From Vittorio Romeo's answer
add a comment |
The difference in behaviour comes from the fact that, according to [dcl.fct.def.default]/5
, bar::bar
is user-provided where foo::foo
is not1. As a consequence, foo::foo
will value-initialize its members (meaning: zero-initialize foo::a
) but bar::bar
will stay uninitialized2.
1)[dcl.fct.def.default]/5
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
2)
From [dcl.init#6]:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
...
From [dcl.init.list]:
List-initialization of an object or reference of type T is defined as follows:
...
Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
From Vittorio Romeo's answer
add a comment |
The difference in behaviour comes from the fact that, according to [dcl.fct.def.default]/5
, bar::bar
is user-provided where foo::foo
is not1. As a consequence, foo::foo
will value-initialize its members (meaning: zero-initialize foo::a
) but bar::bar
will stay uninitialized2.
1)[dcl.fct.def.default]/5
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
2)
From [dcl.init#6]:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
...
From [dcl.init.list]:
List-initialization of an object or reference of type T is defined as follows:
...
Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
From Vittorio Romeo's answer
The difference in behaviour comes from the fact that, according to [dcl.fct.def.default]/5
, bar::bar
is user-provided where foo::foo
is not1. As a consequence, foo::foo
will value-initialize its members (meaning: zero-initialize foo::a
) but bar::bar
will stay uninitialized2.
1)[dcl.fct.def.default]/5
A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration.
2)
From [dcl.init#6]:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type with either no default constructor ([class.ctor]) or a default constructor that is user-provided or deleted, then the object is default-initialized;
if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;
...
From [dcl.init.list]:
List-initialization of an object or reference of type T is defined as follows:
...
Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.
From Vittorio Romeo's answer
edited 11 hours ago
answered 11 hours ago
YSCYSC
21.4k349101
21.4k349101
add a comment |
add a comment |
From cppreference:
Aggregate initialization initializes aggregates. It is a form of list-initialization.
An aggregate is one of the following types:
[snip]
class type [snip], that has
[snip] (there are variations for different standard versions)
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
[snip] (there are more rules, which apply to both classes)
Given this definition, foo
is an aggregate, while bar
is not (it has user-provided, non-defaulted constructor).
Therefore for foo
, T object {arg1, arg2, ...};
is syntax for aggregate initialisation.
The effects of aggregate initialization are:
[snip] (some details irrelevant to this case)
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized.
Therefore a.a
is value initialised, which for int
means zero initialisation.
For bar
, T object {};
on the other hand is value initialisation (of the class instance, not value initialisation of members!). Since it is a class type with a default constructor, the default constructor is called. The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int
(with non-static storage) leaves b.b
with an indeterminate value.
And for pod-types, the default initialization is zero-initialization.
No. This is wrong.
P.S. A word about your experiment and your conclusion: Seeing that output is zero does not necessarily mean that the variable was zero initialised. Zero is perfectly possible number for a garbage value.
for that I ran the program maybe 5~6 times before posting and about 10 times now, a is always zero. b changes around a little.
The fact that the value was same multiple times does not necessarily mean that it was initialised either.
I also tried with set(CMAKE_CXX_STANDARD 14). The result was the same.
The fact that result is the same with multiple compiler options doesn't mean that the variable is initialised. (Although in some cases, changing standard version can change whether it is initialised).
How could I somehow shake my RAM a little so that if there was zero there, it should now be something else
There is no guaranteed way in C++ to make uninitialised value value to appear nonzero.
Only way to know that a variable is initialised is to compare program to the rules of the language and verify that the rules say that it is initialised. In this case a.a
is indeed initialised.
"The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int leaves it with an indeterminate value." --> eh! "for pod-types, the default initialization is zero-initialization." or am I wrong?
– Joey Mallone
11 hours ago
2
@JoeyMallone Default initialization of POD types is no initialization.
– NathanOliver
11 hours ago
@NathanOliver, Then I am even more confused. Then how comea
is initialized. I was thinkinga
is default initialized and default initialization for a member POD is, zero-initialization. Isa
then just luckily always coming up zero, no matter how many times I run this program.
– Joey Mallone
10 hours ago
@JoeyMalloneThen how come a is initialized.
Because it is value initialised.I was thinking a is default initialized
It is not.
– eerorika
10 hours ago
3
@JoeyMallone Don't worry about it. You could make a book out of initialization in C++. If you get a chance CppCon on youtube has a few videos on initialization with the most disappointing (as in pointing out how bad it is) being youtube.com/watch?v=7DTlWPgX6zs
– NathanOliver
10 hours ago
|
show 3 more comments
From cppreference:
Aggregate initialization initializes aggregates. It is a form of list-initialization.
An aggregate is one of the following types:
[snip]
class type [snip], that has
[snip] (there are variations for different standard versions)
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
[snip] (there are more rules, which apply to both classes)
Given this definition, foo
is an aggregate, while bar
is not (it has user-provided, non-defaulted constructor).
Therefore for foo
, T object {arg1, arg2, ...};
is syntax for aggregate initialisation.
The effects of aggregate initialization are:
[snip] (some details irrelevant to this case)
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized.
Therefore a.a
is value initialised, which for int
means zero initialisation.
For bar
, T object {};
on the other hand is value initialisation (of the class instance, not value initialisation of members!). Since it is a class type with a default constructor, the default constructor is called. The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int
(with non-static storage) leaves b.b
with an indeterminate value.
And for pod-types, the default initialization is zero-initialization.
No. This is wrong.
P.S. A word about your experiment and your conclusion: Seeing that output is zero does not necessarily mean that the variable was zero initialised. Zero is perfectly possible number for a garbage value.
for that I ran the program maybe 5~6 times before posting and about 10 times now, a is always zero. b changes around a little.
The fact that the value was same multiple times does not necessarily mean that it was initialised either.
I also tried with set(CMAKE_CXX_STANDARD 14). The result was the same.
The fact that result is the same with multiple compiler options doesn't mean that the variable is initialised. (Although in some cases, changing standard version can change whether it is initialised).
How could I somehow shake my RAM a little so that if there was zero there, it should now be something else
There is no guaranteed way in C++ to make uninitialised value value to appear nonzero.
Only way to know that a variable is initialised is to compare program to the rules of the language and verify that the rules say that it is initialised. In this case a.a
is indeed initialised.
"The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int leaves it with an indeterminate value." --> eh! "for pod-types, the default initialization is zero-initialization." or am I wrong?
– Joey Mallone
11 hours ago
2
@JoeyMallone Default initialization of POD types is no initialization.
– NathanOliver
11 hours ago
@NathanOliver, Then I am even more confused. Then how comea
is initialized. I was thinkinga
is default initialized and default initialization for a member POD is, zero-initialization. Isa
then just luckily always coming up zero, no matter how many times I run this program.
– Joey Mallone
10 hours ago
@JoeyMalloneThen how come a is initialized.
Because it is value initialised.I was thinking a is default initialized
It is not.
– eerorika
10 hours ago
3
@JoeyMallone Don't worry about it. You could make a book out of initialization in C++. If you get a chance CppCon on youtube has a few videos on initialization with the most disappointing (as in pointing out how bad it is) being youtube.com/watch?v=7DTlWPgX6zs
– NathanOliver
10 hours ago
|
show 3 more comments
From cppreference:
Aggregate initialization initializes aggregates. It is a form of list-initialization.
An aggregate is one of the following types:
[snip]
class type [snip], that has
[snip] (there are variations for different standard versions)
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
[snip] (there are more rules, which apply to both classes)
Given this definition, foo
is an aggregate, while bar
is not (it has user-provided, non-defaulted constructor).
Therefore for foo
, T object {arg1, arg2, ...};
is syntax for aggregate initialisation.
The effects of aggregate initialization are:
[snip] (some details irrelevant to this case)
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized.
Therefore a.a
is value initialised, which for int
means zero initialisation.
For bar
, T object {};
on the other hand is value initialisation (of the class instance, not value initialisation of members!). Since it is a class type with a default constructor, the default constructor is called. The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int
(with non-static storage) leaves b.b
with an indeterminate value.
And for pod-types, the default initialization is zero-initialization.
No. This is wrong.
P.S. A word about your experiment and your conclusion: Seeing that output is zero does not necessarily mean that the variable was zero initialised. Zero is perfectly possible number for a garbage value.
for that I ran the program maybe 5~6 times before posting and about 10 times now, a is always zero. b changes around a little.
The fact that the value was same multiple times does not necessarily mean that it was initialised either.
I also tried with set(CMAKE_CXX_STANDARD 14). The result was the same.
The fact that result is the same with multiple compiler options doesn't mean that the variable is initialised. (Although in some cases, changing standard version can change whether it is initialised).
How could I somehow shake my RAM a little so that if there was zero there, it should now be something else
There is no guaranteed way in C++ to make uninitialised value value to appear nonzero.
Only way to know that a variable is initialised is to compare program to the rules of the language and verify that the rules say that it is initialised. In this case a.a
is indeed initialised.
From cppreference:
Aggregate initialization initializes aggregates. It is a form of list-initialization.
An aggregate is one of the following types:
[snip]
class type [snip], that has
[snip] (there are variations for different standard versions)
no user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed)
[snip] (there are more rules, which apply to both classes)
Given this definition, foo
is an aggregate, while bar
is not (it has user-provided, non-defaulted constructor).
Therefore for foo
, T object {arg1, arg2, ...};
is syntax for aggregate initialisation.
The effects of aggregate initialization are:
[snip] (some details irrelevant to this case)
If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are value-initialized.
Therefore a.a
is value initialised, which for int
means zero initialisation.
For bar
, T object {};
on the other hand is value initialisation (of the class instance, not value initialisation of members!). Since it is a class type with a default constructor, the default constructor is called. The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int
(with non-static storage) leaves b.b
with an indeterminate value.
And for pod-types, the default initialization is zero-initialization.
No. This is wrong.
P.S. A word about your experiment and your conclusion: Seeing that output is zero does not necessarily mean that the variable was zero initialised. Zero is perfectly possible number for a garbage value.
for that I ran the program maybe 5~6 times before posting and about 10 times now, a is always zero. b changes around a little.
The fact that the value was same multiple times does not necessarily mean that it was initialised either.
I also tried with set(CMAKE_CXX_STANDARD 14). The result was the same.
The fact that result is the same with multiple compiler options doesn't mean that the variable is initialised. (Although in some cases, changing standard version can change whether it is initialised).
How could I somehow shake my RAM a little so that if there was zero there, it should now be something else
There is no guaranteed way in C++ to make uninitialised value value to appear nonzero.
Only way to know that a variable is initialised is to compare program to the rules of the language and verify that the rules say that it is initialised. In this case a.a
is indeed initialised.
edited 10 hours ago
answered 11 hours ago
eerorikaeerorika
79.2k557119
79.2k557119
"The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int leaves it with an indeterminate value." --> eh! "for pod-types, the default initialization is zero-initialization." or am I wrong?
– Joey Mallone
11 hours ago
2
@JoeyMallone Default initialization of POD types is no initialization.
– NathanOliver
11 hours ago
@NathanOliver, Then I am even more confused. Then how comea
is initialized. I was thinkinga
is default initialized and default initialization for a member POD is, zero-initialization. Isa
then just luckily always coming up zero, no matter how many times I run this program.
– Joey Mallone
10 hours ago
@JoeyMalloneThen how come a is initialized.
Because it is value initialised.I was thinking a is default initialized
It is not.
– eerorika
10 hours ago
3
@JoeyMallone Don't worry about it. You could make a book out of initialization in C++. If you get a chance CppCon on youtube has a few videos on initialization with the most disappointing (as in pointing out how bad it is) being youtube.com/watch?v=7DTlWPgX6zs
– NathanOliver
10 hours ago
|
show 3 more comments
"The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int leaves it with an indeterminate value." --> eh! "for pod-types, the default initialization is zero-initialization." or am I wrong?
– Joey Mallone
11 hours ago
2
@JoeyMallone Default initialization of POD types is no initialization.
– NathanOliver
11 hours ago
@NathanOliver, Then I am even more confused. Then how comea
is initialized. I was thinkinga
is default initialized and default initialization for a member POD is, zero-initialization. Isa
then just luckily always coming up zero, no matter how many times I run this program.
– Joey Mallone
10 hours ago
@JoeyMalloneThen how come a is initialized.
Because it is value initialised.I was thinking a is default initialized
It is not.
– eerorika
10 hours ago
3
@JoeyMallone Don't worry about it. You could make a book out of initialization in C++. If you get a chance CppCon on youtube has a few videos on initialization with the most disappointing (as in pointing out how bad it is) being youtube.com/watch?v=7DTlWPgX6zs
– NathanOliver
10 hours ago
"The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int leaves it with an indeterminate value." --> eh! "for pod-types, the default initialization is zero-initialization." or am I wrong?
– Joey Mallone
11 hours ago
"The default constructor that you defined default initialises the members (by virtue of not having member initialisers), which in case of int leaves it with an indeterminate value." --> eh! "for pod-types, the default initialization is zero-initialization." or am I wrong?
– Joey Mallone
11 hours ago
2
2
@JoeyMallone Default initialization of POD types is no initialization.
– NathanOliver
11 hours ago
@JoeyMallone Default initialization of POD types is no initialization.
– NathanOliver
11 hours ago
@NathanOliver, Then I am even more confused. Then how come
a
is initialized. I was thinking a
is default initialized and default initialization for a member POD is, zero-initialization. Is a
then just luckily always coming up zero, no matter how many times I run this program.– Joey Mallone
10 hours ago
@NathanOliver, Then I am even more confused. Then how come
a
is initialized. I was thinking a
is default initialized and default initialization for a member POD is, zero-initialization. Is a
then just luckily always coming up zero, no matter how many times I run this program.– Joey Mallone
10 hours ago
@JoeyMallone
Then how come a is initialized.
Because it is value initialised. I was thinking a is default initialized
It is not.– eerorika
10 hours ago
@JoeyMallone
Then how come a is initialized.
Because it is value initialised. I was thinking a is default initialized
It is not.– eerorika
10 hours ago
3
3
@JoeyMallone Don't worry about it. You could make a book out of initialization in C++. If you get a chance CppCon on youtube has a few videos on initialization with the most disappointing (as in pointing out how bad it is) being youtube.com/watch?v=7DTlWPgX6zs
– NathanOliver
10 hours ago
@JoeyMallone Don't worry about it. You could make a book out of initialization in C++. If you get a chance CppCon on youtube has a few videos on initialization with the most disappointing (as in pointing out how bad it is) being youtube.com/watch?v=7DTlWPgX6zs
– NathanOliver
10 hours ago
|
show 3 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54350114%2fc-zero-initialization-why-is-b-in-this-program-uninitialized-but-a-is-i%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3
Interestingly, I even get a warning for b: main.cpp:18:34: warning: 'b.bar::b' is used uninitialized in this function [-Wuninitialized] coliru.stacked-crooked.com/a/d1b08a4d6fb4ca7e
– tkausl
11 hours ago
1
@TheQuantumPhysicist, for that I ran the program maybe 5~6 times before posting and about 10 times now,
a
is always zero.b
changes around a little.– Joey Mallone
11 hours ago
5
bar
's constructor is user provided whereasfoo
's constructor is the defaulted one.– Jarod42
11 hours ago
2
@PeteBecker, I understand that. How could I somehow shake my RAM a little so that if there was zero there, it should now be something else. ;) p.s. I ran the program a dozen times. It is not a big program. You could run it and test it on your system.
a
is zero.b
is not. Seemsa
is initialized.– Joey Mallone
11 hours ago
1
@JoeyMallone Regarding "how is it user-provided": There is no guarantee that the definition of
bar::bar()
is visible inmain()
- it might be defined in a separate compilation unit and do something very non-trivial while inmain()
only the declaration is visible. I think you'll agree that this behavior shouldn't change depending on whether you placebar::bar()
's definition in a separate compilation unit or not (even if the whole situation is unintuitive).– Max Langhof
11 hours ago