This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
uninitialized const
I understand that a const object needs to initialized.
So for the following code,
class sample
{};
int main()
{
const sample obj;
return 0;
}
the compiler will complain because the const object obj is not initialized.
But when i modify the code(show below) with a default constructor, the compiler will not throw any error.
class sample
{
public:
sample() { }
};
int main()
{
const sample obj;
return 0;
}
What is the thing that the newly added default ctor does which satisfies the compiler?
What is the thing that the newly added default ctor does which satisfies the compiler?
Because that is the requirement imposed by the C++ standard when declaring objects with the const qualifer.
Reference:
C++03 8.5 Initializers 8 Declarators
§9:
If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a nonstatic object, the object and its subobjects, if any, have an indeterminate initial value90); if the object or any of its subobjects are of const-qualified type, the program is ill-formed.
You're doing a default initialization of a const-qualified type. The C++ (C++11 draft n3290) standard has this to say about that (§8.5/6 Initializers):
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
Your first sample doesn't conform to this (no user-provided constructor). The second does.
Related
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What do the following phrases mean in C++: zero-, default- and value-initialization?
Today I came to know about 3 types of initialization in C++:
Zero Initialization
Default Initialization
Value Initialization
I have googled about it but I found no satisfactory results. All I get is a few standards. What I have understood until now is this: in case of value initialization, a data member can get value equal to zero in some cases.
Please elaborate them (standards) with examples. Also please don't just provide the text from the standard.
Thanks
The types of initialization refer to the language grammar. Here are two examples:
T * p1 = new T;
T * p2 = new T();
The object *p1 is default-initialized, and the object *p2 is value-initialized.
The effect of the initialization depends on the type T: 1) If T is a fundamental, then default-initialization does nothing (i.e. the object is left uninitialized), while value initialization equals zero initialization in that case and means the object is set to zero.
2) If T is an aggregate (i.e. class without constructors or destructor or assignment operator), then each element is recursively default- or value-initialized.
3) If T is of class-type and does have user-defined constructors, then both default- and value-initialization cause a call to the default constructor.
Note that member objects of classes with constructors can in turn be default- or value-initialized:
struct Foo {
int x;
int y;
Foo() : x() { }
};
Now when you say Foo a; then a is default-initialized, so the default constructor is called. This in turn causes a.x to be value-, i.e. zero-initialized, while a.y remains default-, i.e. un-initialized.
(Note that it's not really possible to value-initialize an automatic object, though in C++11, brace-initialization may be used to cause value-initialization, as in Foo a{};. (This behaves exactly the same as Foo a; in our example, consequent to the third paragraph.))
This is dealt with in 8.5 Initializers [dcl.init].
Zero Initialization
5/ 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. As specified in 4.10, converting an integral constant expression whose value is 0 to a pointer type results in a null pointer
value.
— 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 zeroinitialized 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.
Basically, it's equivalent to a memset(&obj, 0, sizeof(objt));, except that it account that the memory representation of a null pointer might not be a 0 value (even though it is represented by a 0 in the language).
// foo.cpp
static char const* p; // p is zero-initialized
// during static initialization
static void init() {
if (!p) { p = new char[500]; } // fine as p has been 0-initialized
}
Note: personally I still prefer to use = nullptr to initialize p, just to make the intent clear...
Default Initialization
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.
If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor.
Or basically, a call to the default constructor, accounting for arrays, at least for classes. The last point is a caveat for built-ins (such as int). Those are simply left as is (with garbage inside).
Default initialization is what is called when you defined a variable but do not initialize it explicitly. It is also what happens to attributes of a class that are not listed in the initializer list. So the caveat for built-ins is quite important to a programmer.
int function() {
int a; // <-- a is default-initialized (which means nothing happens...)
return a; // <-- uses a, so technically undefined behavior
}
struct A { int a; A() {} }; // During the call to A::A(),
// A::a is default-initialized (nothing happens...)
The absence of explicit initialization is a left-over from C. It's normally so for optimization reasons but leads to Undefined Behavior if one attempts to use the value...
Value Initialization
7/ 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.
An object that is value-initialized is deemed to be constructed and thus subject to provisions of this International Standard applying to “constructed” objects, objects “for which the constructor has completed,” etc., even if no constructor is invoked for the object’s initialization.
It is a mix of both the above, meaning that the following syntax:
template <typename T> T value() { return T(); }
^~~
provides a suitably initialized instance of T whether T is a class type or a built-in type. It's important for templated code to be able to have such a unified syntax.
Note that with C++11, it is also possible to use T{} to achieve the same effect (which helps disambiguates from functions).
The C++ standard says (8.5/5):
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.
With this code
struct Int { int i; };
int main()
{
Int a;
}
the object a is default-initialized, but clearly a.i is not necessarily equal to 0 . Doesn't that contradict the standard, as Int is POD and is not an array ?
Edit Changed from class to struct so that Int is a POD.
From 8.5.9 of the 2003 standard:
If no initializer is specified for an object, and the object is of
(possibly cv-qualified) non-POD class type (or array thereof), the
object shall be default-initialized; if the object is of
const-qualified type, the underlying class type shall have a
user-declared default constructor. Otherwise, if no initializer is
specified for a nonstatic object, the object and its subobjects, if
any, have an indeterminate initial value); if the object or any of
its subobjects are of const-qualified type, the program is ill-formed.
The class you show is a POD, so the highlighted part applies, and your object will not be initialized at all (so section 8.5/5, which you quote, does not apply at all).
Edit: As per your comment, here the quote from section 8.5/5 of the final working draft of the current standard (I don't have the real standard, but the FDIS is supposedly very close):
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.
Your variable is not initialized.
Use
Int a = Int();
to initialize your POD or declare a standard constructor to make it non POD;
But you can also use your POD uninitialized for performance reasons like:
Int a;
a.i = 5;
No, the object a is not default-initialized. If you want to default-initialize it, you have to say:
Int a = Int() ;
I've been wondering about the language in the C++03 specification surrounding object initialization, specifically section 8.5 paragraph 9 which states,
"If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or
array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying
class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a nonstatic
object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any
of its subobjects are of const-qualified type, the program is ill-formed."
I want to pay particular attention to the clause, "Otherwise, if no initializer is specified for a nonstatic
object, the object and its subobjects, if any, have an indeterminate initial value". According to section 8.5 paragraph 5, the definition of a default-initialization falls into three cases:
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.
So as I understand it, paragraph 9 is stating that if we have a non-POD class type that does not have an initializer, then it's default constructor would be called. What I'm confused by is what happens in the case of POD-class types ... it seems from the clause I highlighted that there is no mention of a default constructor call being required for POD-class types. Yet if I created a POD-class type like
struct POD_class
{
int a;
int b;
POD_class() { cout << "Default constructor called" << endl; }
};
int main()
{
POD_class test;
return 0;
}
the default constructor of POD_class seems to be called when this code is compiled and run with g++. Therefore, even if POD_class did not have a specific initializer, it seems it was still default-initialized, per case #1 in the definition of default-initialization, because a default constructor for the type was called.
Based on the above scenario, here is my question: For a POD-class, does not default initializing an object as paragraph 9 mentions for non-static POD-classes mean that its default constructor is not called, or that it's simply not zero-initialized?
Your POD_class is in fact not a POD class. A POD class cannot have a user-declared constructor.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What do the following phrases mean in C++: zero-, default- and value-initialization?
I am confused about an issue in C++.
When creating an object on the stack using the default constructor, I thought either one of the following two syntax notations would give the same result:
class MyClass { public: int i; }
int main()
{
MyClass a = MyClass();
MyClass b;
}
However, the first syntax initializes the field to zero, whereas the second one leaves the field uninitialized. So my questions are:
Why is this so? I thought fields in C++ were not supposed to be automatically initialized.
Is there any other differences between the two syntaxes?
Do these syntax variations have separate names to distinguish them from each other?
I’m currently using Microsoft Visual C++ 2010 Express.
Thanks!
In the first, you copy-initialize a from a value-initialized instance of MyClass. From the C++03 standard, §8.5/7:
An object whose initializer is an empty set of parentheses, i.e., (), shall be value-initialized.
And from §8.5/5:
To value-initialize an object of type T means:
if T is a class type with a user-declared constructor, 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
To zero-initialize an object of type T means:
if T is a scalar type, 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 zero-initialized;
if T is a union type, the object’s first named data member) is zero-initialized;
if T is an array type, each element is zero-initialized;
if T is a reference type, no initialization is performed.
In the second, you declare b in a manner that would cause it to be default-initialized if MyClass were not a POD type -- §8.5/5:
To default-initialize an object of type T means:
if T is a non-POD class type, 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.
However, because MyClass is a POD type, b is uninitialized -- §8.5/9:
If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a non-static object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.
Basically, this is a (relatively) simple WTF in the language, where primitive types will not be initialized by default. The first syntax explicitly initializes them- the second doesn't. User-defined types will always be initialized, so it's only meaningful if you don't initialize it in the constructor, and it will be an error if you don't call the init functions of UDTs that need them.
UDTs that do not do anything insane should not require the first syntax and it's normal to use the second.
Here is simple program.
If I comment constructor, I get an error
Just wanted to check what is the reason for this?
t.cc: In function 'int main(int, char**)':
t.cc:26: error: uninitialized const 'const_test'
#include <iostream>
using namespace std;
class TestPrint
{
public:
// TestPrint() {}
void Print()
{
std::cout << "TestPrint" << std::endl;
}
void Print() const
{
std::cout << "const TestPrint" << std::endl;
}
};
int main(int argc, char* argv[])
{
TestPrint normal_test;
normal_test.Print();
const TestPrint const_test;
const_test.Print();
}
It is indeed ill-formed. §8.5/9:
If no initializer is specified for an object, and the object is of (possibly cv-qualified) non-POD class type (or array thereof), the object shall be default-initialized; if the object is of const-qualified type, the underlying class type shall have a user-declared default constructor. Otherwise, if no initializer is specified for a nonstatic object, the object and its subobjects, if any, have an indeterminate initial value; if the object or any of its subobjects are of const-qualified type, the program is ill-formed.
Emphasis mine. Any compiler that does not issue a diagnosis for your program is non-compliant (looking at you MSVC). A simpler test:
struct foo {};
int main()
{
const foo f;
}
The idea is simple: constants need to be initialized to something. If you have no user-defined constructor, you have no initialization.
According to the ISO standard (8.5 [dcl.init] paragraph 9):
If no initializer is specified for an object, and the object is of
(possibly cv-qualified) non-POD class type (or array thereof), the
object shall be default-initialized; if the object is of
const-qualified type, the underlying class type shall have a
user-declared default constructor.
So GCC is right here. Sorry, VC guys.
A const-qualified object must be initialised where it is defined; either by an initialiser (e.g. const TestPrint const_test = TestPrint();), or by a default constructor. This rule applies to all objects, even if they don't have any data members to initialise.
So without the default constructor, your code is ill-formed; with it, it is fine and the default constructor is used for initialisation.
Your code compiles in Microsoft Visual Studio 2008. Perhaps this is a bug with your compiler, what compiler are you using?