I had always thought that creating a new object would always call the default constructor on an object, and whether the constructor was explicit or automatically generated by the compiler made no difference. According to this highly regarded answer to a different question, this changed in a subtle way between C++98 and C++03 and now works like so:
struct B { ~B(); int m; }; // non-POD, compiler generated default ctor
new B; // default-initializes (leaves B::m uninitialized)
new B(); // value-initializes B which zero-initializes all fields since its default ctor is compiler generated as opposed to user-defined.
Can anyone tell me:
Why was the standard changed, i.e. what advantage does this give or what is now possible that wasn't before;
What exacly do the terms "default-initialize" and "value-initialize" represent?
What's the relevant part of the standard?
I do not know what the rationales around the change (or how the standard was before), but on how it is, basically default-initialization is either calling a user defined constructor or doing nothing (lots of hand-waving here: this is recursively applied to each subobject, which means that the subobjects with a default constructor will be initialized, the subobjects with no user defined constructors will be left uninitialized).
This falls within the only pay for what you want philosophy of the language and is compatible with C in all the types that are C compatible. On the other hand, you can request value-initialization, and that is the equivalent to calling the default constructor for objects that have it or initializing to 0 converted to the appropriate type for the rest of the subobjects.
This is described in §8.5 Initializers, and it is not trivial to navigate through. The definitions for zero-initialize, default-initialize and value-initialize are the 5th paragraph:
To zero-initialize an object of type T means:
— if T is a scalar type (3.9), the object is set to the value of 0 (zero) converted to T;
— if T is a non-union class type, each nonstatic data member and each base-class subobject is zeroinitialized;
— if T is a union type, the object’s first named data member89) is zero-initialized;
— if T is an array type, each element is zero-initialized;
— if T is a reference type, no initialization is performed.
To default-initialize an object of type T means:
— if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is an array type, each element is default-initialized;
— otherwise, the object is zero-initialized.
To value-initialize an object of type T means:
— if T is a class type (clause 9) with a user-declared constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;
— if T is an array type, then each element is value-initialized;
— otherwise, the object is zero-initialized
A program that calls for default-initialization or value-initialization of an entity of reference type is illformed. If T is a cv-qualified type, the cv-unqualified version of T is used for these definitions of zeroinitialization, default-initialization, and value-initialization.
Related
Consider the following code:
class A {
public:
int i;
A() {}
};
class B {
public:
A a;
int i;
};
int main() {
B* p = new B {};
std::cout << p->i << " " << p->a.i << "\n";
}
Compiled with -std=c++11 in clang++, p->i turns out to be zero, but p->a.i doesn't. Shouldn't the whole object be zeroed as long as its class doesn't have user-provided constructor?
EDIT: Since there are some extensive discussion in the comments, I think it's better to add some excerpt from the standard here:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized.
To zero-initialize an object or reference of type T means:
if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression, converted to T;
if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized and padding is initialized to zero bits;
if T is a (possibly cv-qualified) union type, the object’s first non-static named data member is zero-initialized and padding is initialized to zero bits;
if T is an array type, each element is zero-initialized;
if T is a reference type, no initialization is performed.
The second bullet of each applies here.
Clang is correct, per the C++11 standard plus relevant DRs
In the original C++11 specification, B{} would perform value-initialization, resulting in a.i being zero-initialized. This was a change in behavior compared to C++98 for cases like
B b = {};
... which were handled as aggregate initialization in C++98 but treated as value-initialization in C++11 FDIS.
However, the behavior in this case was changed by core issue 1301, which restored the C++98 behavior by mandating that aggregate initialization is used whenever an aggregate is initialized by a braced-init-list. Since this issue is considered a DR, it is treated as de facto applying to earlier revisions of the C++ standard, so a conforming C++11 compiler would be expected to perform aggregate initialization here rather than value-initialization.
Ultimately, it's a bad idea to rely on value-initialization to initialize your data members, especially for a class that has user-provided constructors.
It does indeed look like a bug (or, as pointed out in the comments, behaving according to C++03 despite specifying C++11). In C++11, value-initialisation should zero the members of a before calling its default constructor. Initialisation of B is governed by this rule of 8.5/7
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
The zero-initialisation should recursively zero-initialise a per this rule of 8.5/5
if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized
and, of course, zero-initialisation of a should set i to zero.
It is not a compiler bug, it is a bug in your code. The compiler seems to be implementing the C++03 behaviour, but this has crucially changed in C++11.
These are some relevant quotes from the C++03 and C++11 standards
In C++03:
To value-initialize an object of type T means:
— if T is a class type
(clause 9) with a user-declared constructor (12.1), then the default
constructor for T is called (and the initialization is ill-formed if T
has no accessible default constructor);
— if T is a non-union class
type without a user-declared constructor, then every non-static data
member and base-class component of T is value-initialized;
(emphasis mine)
In C++11:
To value-initialize an object of type T means:
— if T is a (possibly
cv-qualified) class type (Clause 9) with a user-provided constructor
(12.1), then the default constructor for T is called (and the
initialization is ill-formed if T has no accessible default
constructor);
— if T is a (possibly cv-qualified) non-union class type
without a user-provided constructor, then the object is
zero-initialized and, if T’s implicitly-declared default constructor
is non-trivial, that constructor is called.
and
To zero-initialize an object or reference of type T means:
— if T is a
scalar type (3.9), the object is set to the value 0 (zero), taken as
an integral constant expression, converted to T;
if T is a
(possibly cv-qualified) non-union class type, each non-static data
member and each base-class subobject is zero-initialized and padding
is initialized to zero bits;
Note: The following only applies to C++03:
Either remove A's user-provided constructor, or change it to
A() : i() {}
When you value-initialize a B here,
B* p = new B {};
it value-initializes its data members. Since A has a default constructor, the value-initialization results in a call to that. But that constructor does not explicitly initialize A::i, so it gets default-initialized, which for an int means no initialization is performed.
If you had not provided a default constructor for A, then the data member would get zero-initialized when an A is value-initialized.
Integral types are not required to be initialized to a value like that in a non-default constructor (since you have provided a constructor)
Change your constructor to A() : i(0) {}.
I could swear I don't remember having seen this before, and I'm having trouble believing my eyes:
Does an implicitly-defined default constructor for a non-aggregate class initialize its members or no?
In Visual C++, when I run this innocent-looking code...
#include <string>
struct S { int a; std::string b; };
int main() { return S().a; }
... to my astonishment, it returns a non-zero value! But if I remove field b, then it returns zero.
I've tried this on all versions of VC++ I can get my hands on, and it seems to do this on all of them.
But when I try it on Clang and GCC, the values are initialized to zero, whether I try it in C++98 mode or C++11 mode.
What's the correct behavior? Is it not guaranteed to be zero?
Quoting C++11:
5.2.3 Explicit type conversion (functional notation) [expr.type.conv]
2 The expression T(), where T is a simple-type-specifier or typename-specifier for a non-array complete object type or the (possibly cv-qualified) void type, creates a prvalue of the specified type,which is value-initialized (8.5; no initialization is done for the void() case). [...]
8.5 Initializers [dcl.init]
7 To value-initialize an object of type T means:
...
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T's implicitly-declared default constructor is non-trivial, that constructor is called.
...
So in C++11, S().a should be zero: the object is zero-initialized before the constructor gets called, and the constructor never changes the value of a to anything else.
Prior to C++11, value initialization had a different description. Quoting N1577 (roughly C++03):
To value-initialize an object of type T means:
...
if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class component of T is value-initialized;
...
otherwise, the object is zero-initialized
Here, value initialization of S did not call any constructor, but caused value initialization of its a and b members. Value initialization of that a member, then, caused zero initialization of that specific member. In C++03, the result was also guaranteed to be zero.
Even earlier than that, going to the very first standard, C++98:
The expression T(), where T is a simple-type-specifier (7.1.5.2) for a non-array complete object type or the (possibly cv-qualified) void type, creates an rvalue of the specified type, whose value is determined by default-initialization (8.5; no initialization is done for the void() case).
To default-initialize an object of type T means:
if T is a non-POD class type (clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
...
otherwise, the storage for the object is zero-initialized.
So based on that very first standard, VC++ is correct: when you add a std::string member, S becomes a non-POD type, and non-POD types don't get zero initialization, they just have their constructor called. The implicitly generated default constructor for S does not initialise the a member.
So all compilers can be said to be correct, just following different versions of the standard.
As reported by #Columbo in the comments, later versions of VC++ do cause the a member to be initialized, in accordance with more recent versions of the C++ standard.
(All quotes in the first section are from N3337, C++11 FD with editorial changes)
I cannot reproduce the behavior with the VC++ on rextester. Presumably the bug (see below) is already fixed in the version they are using, but not in yours - #Drop reports that the latest release, VS 2013 Update 4, fails the assertion - while the VS 2015 preview passes them.
Just to avoid misunderstandings: S is indeed an aggregate. [dcl.init.aggr]/1:
An aggregate is an array or a class (Clause 9) with no user-provided
constructors (12.1), no private or protected non-static data members
(Clause 11), no base classes (Clause 10), and no virtual functions
(10.3).
That is irrelevant though.
The semantics of value initialization are important. [dcl.init]/11:
An object whose initializer is an empty set of parentheses, i.e.,
(), shall be value-initialized.
[dcl.init]/8:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9) with either no default constructor (12.1) 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;
[..]
Clearly this holds regardless of whether b is in S or not. So at least in C++11 in both cases a should be zero. Clang and GCC show the correct behavior.
And now let's have a look at the C++03 FD:
To value-initialize an object of type T means:
if T is a class type (clause 9) with a user-declared constructor (12.1) [..]
if T is a non-union class type without a user-declared constructor, then every non-static data member and base-class
component of T is value-initialized;
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized
That is, even in C++03 (where the above quote in [dcl.init]/11 also exists in /7), a should be 0 in both cases.
Again, both GCC and Clang are correct with -std=c++03.
As shown in hvd's answer, your version is compliant for C++98, and C++98 only.
Consider the following code:
class A {
public:
int i;
A() {}
};
class B {
public:
A a;
int i;
};
int main() {
B* p = new B {};
std::cout << p->i << " " << p->a.i << "\n";
}
Compiled with -std=c++11 in clang++, p->i turns out to be zero, but p->a.i doesn't. Shouldn't the whole object be zeroed as long as its class doesn't have user-provided constructor?
EDIT: Since there are some extensive discussion in the comments, I think it's better to add some excerpt from the standard here:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
if T is an array type, then each element is value-initialized;
otherwise, the object is zero-initialized.
To zero-initialize an object or reference of type T means:
if T is a scalar type (3.9), the object is set to the value 0 (zero), taken as an integral constant expression, converted to T;
if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized and padding is initialized to zero bits;
if T is a (possibly cv-qualified) union type, the object’s first non-static named data member is zero-initialized and padding is initialized to zero bits;
if T is an array type, each element is zero-initialized;
if T is a reference type, no initialization is performed.
The second bullet of each applies here.
Clang is correct, per the C++11 standard plus relevant DRs
In the original C++11 specification, B{} would perform value-initialization, resulting in a.i being zero-initialized. This was a change in behavior compared to C++98 for cases like
B b = {};
... which were handled as aggregate initialization in C++98 but treated as value-initialization in C++11 FDIS.
However, the behavior in this case was changed by core issue 1301, which restored the C++98 behavior by mandating that aggregate initialization is used whenever an aggregate is initialized by a braced-init-list. Since this issue is considered a DR, it is treated as de facto applying to earlier revisions of the C++ standard, so a conforming C++11 compiler would be expected to perform aggregate initialization here rather than value-initialization.
Ultimately, it's a bad idea to rely on value-initialization to initialize your data members, especially for a class that has user-provided constructors.
It does indeed look like a bug (or, as pointed out in the comments, behaving according to C++03 despite specifying C++11). In C++11, value-initialisation should zero the members of a before calling its default constructor. Initialisation of B is governed by this rule of 8.5/7
if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
The zero-initialisation should recursively zero-initialise a per this rule of 8.5/5
if T is a (possibly cv-qualified) non-union class type, each non-static data member and each base-class subobject is zero-initialized
and, of course, zero-initialisation of a should set i to zero.
It is not a compiler bug, it is a bug in your code. The compiler seems to be implementing the C++03 behaviour, but this has crucially changed in C++11.
These are some relevant quotes from the C++03 and C++11 standards
In C++03:
To value-initialize an object of type T means:
— if T is a class type
(clause 9) with a user-declared constructor (12.1), then the default
constructor for T is called (and the initialization is ill-formed if T
has no accessible default constructor);
— if T is a non-union class
type without a user-declared constructor, then every non-static data
member and base-class component of T is value-initialized;
(emphasis mine)
In C++11:
To value-initialize an object of type T means:
— if T is a (possibly
cv-qualified) class type (Clause 9) with a user-provided constructor
(12.1), then the default constructor for T is called (and the
initialization is ill-formed if T has no accessible default
constructor);
— if T is a (possibly cv-qualified) non-union class type
without a user-provided constructor, then the object is
zero-initialized and, if T’s implicitly-declared default constructor
is non-trivial, that constructor is called.
and
To zero-initialize an object or reference of type T means:
— if T is a
scalar type (3.9), the object is set to the value 0 (zero), taken as
an integral constant expression, converted to T;
if T is a
(possibly cv-qualified) non-union class type, each non-static data
member and each base-class subobject is zero-initialized and padding
is initialized to zero bits;
Note: The following only applies to C++03:
Either remove A's user-provided constructor, or change it to
A() : i() {}
When you value-initialize a B here,
B* p = new B {};
it value-initializes its data members. Since A has a default constructor, the value-initialization results in a call to that. But that constructor does not explicitly initialize A::i, so it gets default-initialized, which for an int means no initialization is performed.
If you had not provided a default constructor for A, then the data member would get zero-initialized when an A is value-initialized.
Integral types are not required to be initialized to a value like that in a non-default constructor (since you have provided a constructor)
Change your constructor to A() : i(0) {}.
Does the C++ standard guarantee that uninitialized POD members retain their previous value after a placement new?
Or more precisely, will the following assert always be satisfied according to C++11?
#include <cstdlib>
#include <cassert>
struct Foo {
int alpha; // NOTE: Uninitialized
int beta = 0;
};
int main()
{
void* p = std::malloc(sizeof (Foo));
int i = some_random_integer();
static_cast<Foo*>(p)->alpha = i;
new (p) Foo;
assert(static_cast<Foo*>(p)->alpha == i);
}
Is the answer the same for C++03?
Does the C++ standard guarantee that uninitialized POD members retain their previous value after a placement new?
Will the following assert always be satisfied according to C++11?
No.
Uninitialized data members have an indeterminate value, and this is not at all the same as saying that the underlying memory is left alone.
[C++11: 5.3.4/15]: A new-expression that creates an object of type T initializes that object as follows:
If the new-initializer is omitted, the object is default-initialized (8.5); if no initialization is performed, the object has indeterminate value.
Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct-initialization.
[C++11: 8.5/6]: To default-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is an array type, each element is default-initialized;
otherwise, no initialization is performed.
[C++11: 12.1/6]: A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odr-used (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of initializations of the class that would be
performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty compound-statement.
[C++11: 12.6.2/8]: In a non-delegating constructor, if a given non-static data member or base class is not designated by a mem-initializer-id (including the case where there is no mem-initializer-list because the constructor has no ctor-initializer) and the entity is not a virtual base class of an abstract class (10.4), then
if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in 8.5;
otherwise, if the entity is a variant member (9.5), no initialization is performed;
otherwise, the entity is default-initialized (8.5).
(NB. the first option in 12.6.2/8 is how your member beta is handled)
[C++11: 8.5/6]: To default-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
if T is an array type, each element is default-initialized;
otherwise, no initialization is performed.
[C++11: 8.5/11]: If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value.
A compiler could choose to zero-out (or otherwise alter) the underlying memory during allocation. For example, Visual Studio in debug mode is known to write recognisable values such as 0xDEADBEEF into memory to aid debugging; in this case, you're likely to see 0xCDCDCDCD which they use to mean "clean memory" (reference).
Will it, in this case? I don't know. I don't think that we can know.
What we do know is that C++ doesn't prohibit it, and I believe that brings us to the conclusion of this answer. :)
Is the answer the same for C++03?
Yes, though through slightly different logic:
[C++03: 5.3.4/15]: A new-expression that creates an object of type T initializes that object as follows:
If the new-initializer is omitted:
If T is a (possibly cv-qualified) non-POD class type (or array thereof), the object is default-initialized (8.5). If T is a const-qualified type, the underlying class type shall have a user-declared default constructor.
Otherwise, the object created has indeterminate value. If T is a const-qualified type, or a (possibly cv-qualified) POD class type (or array thereof) containing (directly or indirectly) a member of const-qualified type, the program is ill-formed;
If the new-initializer is of the form (), the item is value-initialized (8.5);
If the new-initializer is of the form (expression-list) and T is a class type, the appropriate constructor is called, using expression-list as the arguments (8.5);
If the new-initializer is of the form (expression-list) and T is an arithmetic, enumeration, pointer, or pointer-to-member type and expression-list comprises exactly one expression, then the object is initialized to the (possibly converted) value of the expression (8.5);
Otherwise the new-expression is ill-formed.
Now, all that was my strict interpretation of the rules of initialisation.
Speaking practically, I think you're probably correct in seeing a potential conflict with the definition of placement operator new syntax:
[C++11: 18.6.1/3]: Remarks: Intentionally performs no other action.
An example that follows explains that placement new "can be useful for constructing an object at a known address".
However, it doesn't actually talk about the common use of constructing an object at a known address without mungling the values that were already there, but the phrase "performs no other action" does suggest that the intention is that your "indeterminate value" be whatever was in memory previously.
Alternatively, it may simply prohibit the operator itself from taking any action, leaving the allocator free to. It does seem to me that the important point the standard trying to make is that no new memory is allocated.
Regardless, accessing this data invokes undefined behaviour:
[C++11: 4.1/1]: A glvalue (3.10) of a non-function, non-array type T can be converted to a prvalue. If T is an incomplete type, a program that necessitates this conversion is ill-formed. If the object to which the glvalue refers is not
an object of type T and is not an object of a type derived from T, or if the object is uninitialized, a program that necessitates this conversion has undefined behavior. If T is a non-class type, the type of the prvalue is the cv-unqualified version of T. Otherwise, the type of the prvalue is T.
So it doesn't really matter: you couldn't compliantly observe the original value anyway.
C++11 12.6.2/8 "Initializing bases and members" says:
In a non-delegating constructor, if a given non-static data member or
base class is not designated by a mem-initializer-id (including the
case where there is no mem-initializer-list because the constructor
has no ctor-initializer) and the entity is not a virtual base class of
an abstract class (10.4), then
if the entity is a non-static data member that has a brace-or-equal-initializer, the entity is initialized as specified in
8.5;
otherwise, if the entity is a variant member (9.5), no initialization is performed;
otherwise, the entity is default-initialized (8.5).
Default initialization on an int does nothing (8.5/6 "Initializers"):
To default-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is
ill-formed if T has no accessible default constructor);
if T is an array type, each element is default-initialized;
otherwise, no initialization is performed.
So the member alpha should be left alone.
I only just learned yesterday that specifying parameters to initializer list items is optional. However, what are the rules for what happens in this case?
In the below example, will ptr be initialized to 0, toggle to false, and Bar default-constructed? I guess this question is sort of redundant, because there would be little point in initializer lists if unspecified argument values == undefined behavior.
Could I also be pointed to the section of the C++ standard that states the behavior in the case of initializer list items not being given arguments?
class Bar
{
Bar() { }
};
class SomeClass;
class AnotherClass
{
public:
SomeClass *ptr;
bool toggle;
Bar bar;
AnotherClass() : ptr(), toggle(), bar() { }
// as opposed to...
// AnotherClass() : ptr(NULL), toggle(false), bar(Bar()) { }
};
Yes, the members will be initialized to zero and a default-constructed object respectively.
The C++ 11 standard specifies this behavior in 12.6.2/7:
The expression-list or braced-init-list in a mem-initializer is used
to initialize the designated subobject (or, in the case of a
delegating constructor, the complete class object) according to the
initialization rules of 8.5 for direct-initialization.
In turn, 8.5/10 reads:
An object whose initializer is an empty set of parentheses, i.e., (),
shall be value-initialized.
Paragraph 8.5/7 defines value-initialized:
To value-initialize an object of type T means:
if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor
(12.1), then the default constructor for T is called (and the
initialization is ill-formed if T has no accessible default
constructor);
if T is a (possibly cv-qualified) non-union class type
without a user-provided constructor, then the object is
zero-initialized and, if T’s implicitly-declared default constructor
is non-trivial, that constructor is called.
if T is an array type,
then each element is value-initialized;
otherwise, the object is
zero-initialized.
And finally, 8.5/5 defines zero-initialized:
To zero-initialize an object or reference of type T means:
if T is a
scalar type (3.9), the object is set to the value 0 (zero), taken as
an integral constant expression, converted to T;
if T is a
(possibly cv-qualified) non-union class type, each non-static data
member and each base-class subobject is zero-initialized and padding
is initialized to zero bits;
if T is a (possibly cv-qualified) union
type, the object’s first non-static named data member is zero-
initialized and padding is initialized to zero bits;
if T is an
array type, each element is zero-initialized;
if T is a reference
type, no initialization is performed.
In the below example, will ptr be initialized to 0, toggle to false, and Bar default-constructed?
Yes. If a member initialiser appears in the initialiser list with empty parentheses, then that member is value initialised. This means that numerical types will be initialised to zero, pointers to null, and classes with default constructors using that constructor.
If you don't include the member in the initialiser list at all, then it will instead be default initialised; in that case. numerical and pointer types will be left uninitialised.
Could I also be pointed to the section of the C++ standard that states the behavior in the case of initializer list items not being given arguments?
C++11 12.6.2/7 specifies that the rules are the same as for direct initialisation.
C++11 8.5/16 specifies that if the initialiser is (), the object is value-initialised.
C++11 8.5/7 defines value initialisation.
Initialisations are covered in [dcl.init] (aka 8.5)
Point 10 says:
An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
Value-initialisation is, put simply, default construction for classes and zero-initialisation for non-class types.