This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What do the following phrases mean in C++: zero-, default- and value-initialization?
There are multiple places where people have said that an explicit call to the class constructor results in value initialization [when no used-defined constructors exist] and that this is not done by the default constructor [which is a do-nothing constructor] but is something completely different.
What happens actually if no constructor is called OR What is value initialization in this case ?
Firstly, what happens actually if no constructor is called
A constructor for a class-type is always called when an object is constructed, be it user-defined or compiler-generated. The object is initialized, but the members can remain un-initialized. This makes the second part of the question obsolete.
Second, is there documentation that supports/mentions/explains this behaviour ?
The all-mighty standard.
This is only true for aggregates: Consider this:
struct Holder
{
Aggregate a;
NonAggr n;
Holder(int, char) : a(), n() { }
Holder(char, int) { }
};
Holder h1(1, 'a');
Holder h2('b', 2);
Suppose Aggregate is an aggregate type. Now h1.a is value-initialized, which value-initializes each member, while h2.a is default-initialized, which default-initializes each member. The same holds for the n member, but if NonAggr is a non-aggregate class type, its default constructor will always be called.
Related
This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 6 years ago.
When declaring an array of objects, are all the objects constructed at initialization, or do they have to be constructed after initialization? Here is an example of what I am trying to explain:
Lets say I have this class:
class Object{
public:
int x = 4;
};
And this array:
Object objects[8];
If I was to access any of the variables within the objects, would I have to construct the objects first, or was that done in the array? So if I did this:
cout << objects[4].x;
Would it print out 4?
In C++11 your code is perfectly valid, it performs in-class initialization, and indeed, cout << objects[4].x; will print out 4. In previous C++ versions (C++98/03), the code is invalid, and you'd need a default constructor to initialize the variable x, like
class Object{
public:
int x;
Object(int x = 4): x(x){}
}
are all the objects constructed at initialization
Yes, all of elements of array will be default initialized.
if T is an array type, every element of the array is default-initialized;
And
if T is a non-POD (until C++11) class type, the constructors are considered and subjected to overload resolution against the empty argument list. The constructor selected (which is one of the default constructors) is called to provide the initial value for the new object;
And
Would it print out 4?
Yes. For class Object, the implicitly-declared default constructor will be invoked here. And the member x is not initialized by the member initializer list (in default constructor), the default member initializer is applied, then x will be initialized with value 4.
I have had the following structure:
struct MyStruct
{
struct Displacement
{
bool isWrapped;
int steps;
};
int initialDuration;
int currentDuration;
Displacement displacement1;
Displacement displacement2;
};
And I was using it like this:
MyStruct obj{2, 2};
auto shared = std::make_shared<MyStruct>(obj);
The problem was that I needed to duplicate first two arguments as initialDuration and currentDuration should be the same when a new object is created. Therefore I have created a CTOR:
struct MyStruct
{
struct Displacement
{
bool isWrapped;
int steps;
};
MyStruct(int duration)
: initialDuration(duration)
, currentDuration(duration)
{
}
int initialDuration;
int currentDuration;
Displacement displacement1;
Displacement displacement2;
};
and then used like this:
auto shared = std::make_shared<MyStruct>(2);
The unexpected thing 1 is: both Displacement members of MyStruct have been initialized with garbage. For one the bool member of true, for the other one - false and ints were some arbitrary numbers.
So though maybe I need to define CTOR for Displacement too. Defined like this:
struct Displacement
{
Displacement() : isWrapped(false), steps(0) {}
bool isWrapped;
int steps;
};
The unexpected thing 2 is: that somewhere else
MyStruct::Displacement d {false, 0};
started to not compile. I don't know aggregate initialization or list-initialization stopped working for a POD struct when I have defined the default CTOR.
Please explain the reasons of those 2 behaviours.
For your 1st question
both Displacement members of MyStruct have been initialized with garbage.
(from comment) There should be a default CTOR for Displacement defined by the compiler which should be called in the CTOR of MyStruct that I have defined, right?
The implicitly-defined default constructor won't do anything here.
If the implicitly-declared default constructor is not defined as deleted, it is defined (that is, a function body is generated and compiled) by the compiler, and it has exactly the same effect as a user-defined constructor with empty body and empty initializer list. That is, it calls the default constructors of the bases and of the non-static members of this class.
And for MyStruct obj{2, 2};, obj is an automatic object, so (from standard $8.5/12 Initializers [dcl.init])
If no initializer is specified for an object, the object is default-initialized. When storage for an object
with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if
no initialization is performed for the object, that object retains an indeterminate value until that value is
replaced (5.18). [ Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2. —
end note ]
You might want to initialize them as
MyStruct obj{2, 2, {false, 0}, {false, 0}};
For your 2nd question
I don't know aggregate initialization or list-initialization stopped working for a POD struct when I have defined the default CTOR.
Yes it does, unless you provide another ctor which takes std::initializer_list as its parameter. See aggregate initialization
An aggregate is an object of the type that is one of the following
array type
class type (typically, struct or union), that has
no private or protected non-static data members
no user-provided constructors (explicitly defaulted or deleted constructors are allowed) (since C++11)
no base classes
no virtual member functions
no default member initializers (since C++11) (until C++14)
If you have a constructor that is called you need to explicitly initialize all members, or they will be uninitialized. Uninitialized members will have indeterminate values which is what you perceive as garbage. That's how C++ work when you have constructors.
From this implicit default constructor reference:
If the implicitly-declared default constructor is not defined as deleted, it is defined ... by the compiler, and it has exactly the same effect as a user-defined constructor with empty body and empty initializer list. That is, it calls the default constructors of the bases and of the non-static members of this class.
Built-in or aggregate types have no constructor, and so can't be constructed or initialized without an explicit initialization.
Your struct is no longer a POD type when you add a default constructor. Among other things, a POD type must have a trivial default constructor.
You need to add a constructor that takes two arguments for your code to start working again. Also note that the default constructor does not 0-initialize members. The reason it worked before with the POD type is that doing aggregate initialization (which only works with POD types) defaults members not explicitly initialized to 0.
I have searched previous questions, and have not found a satisfying answer to my question:
If I define an empty default constructor for a class, as for example
class my_class{
public:
myclass(){}
private:
int a;
int* b;
std::vector<int> c;
}
my understanding is that if I define an object using the default constructor, say
my_class my_object;
then my_object.a will be a random value, the pointer my_object.b will also be a random value, however the vector c will be a well-behaved, empty vector.
In other words, the default constructor of c is called while the default constructors of a and b is not. Am I understanding this correctly? What is the reason for this?
Thank you!
a and b have non-class types, meaning that they have no constructors at all. Otherwise, your description is correct: my_object.a and my_object.b will have indeterminate values, while my_object.c will be properly constructed.
As for why... by writing a user-defined constructor and not mentioning a and b in the initializer list (and not using C++11 in-class member initializers) you explicitly asked the compiler to leave these members uninitialized.
Note that if your class did not have a user-defined constructor, you'd be able to control the initial values of my_object.a and my_object.b from outside, by specifying initializers at the point of object declaration
my_class my_object1;
// Garbage in `my_object1.a` and `my_object1.b`
my_class my_object2{};
// Zero in `my_object2.a` and null pointer in `my_object2.b`
But when you wrote your own default constructor, you effectively told the compiler that you want to "override" this initialization behavior and do everything yourself.
Since a and b are not objects but primitive datatypes, there is no constructor to call. In contrast, c is an object, so its default constructor is called.
I read following links :-
object initialized with and without parentheses
types of default constructor
diff b/w value,zero and default intilization
I have some question which i want to clarify.
1) Given a POD class , say :-
class A{
int val;
};
If i create an object of type A.
A obj; // will this call implicitly defined constructor provided by compiler ?
Now as far as my understanding in this case constructor is not called.is it correct?
new A(); // value-initialize A, which is zero-initialization since it's a POD.
Now in this case will implicitly defined constructor provided by compiler ? Is there is any role of constructor for zero initializing the object?
If my understanding is wrong , could you please give me an example where implicitly defined defined constructor is not called at all.
Thank you in advance.
1) Correct. obj.val is not initialized.
2) This is a function declaration, not an initialization:
A obj(); // function obj() returning an A
If you did this,
A obj{}; //C++11
A obj = A(); // C++03 and C++11
obj would be value-initialized, and so would obj.val. This in turn means that obj.val would be zero-initialized (value-initialization means zero-initialization for built-in types).
A obj;
It calls default constructor (or even not for optimization), however default constructor doesn't initialize it.
A obj();
It's a function declaration. No arguments and returns A.
A obj{};
Instead, you can use above code which sets val to zero.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How are C array members handled in copy control functions?
If I don't override the operator = of a class, it will use default memberwise assignment.
But what does it mean?
struct A {
int array[100];
};
A a;
A b=a;
No error. How does b copes a'sarray? Normally array_b = array_a is invalid.
Another exampe:
struct A {
vector<int> vec;
};
A a;
A b=a;
How does b copes a'svec? Through assignment(vec_b = vec_a), constructor(vec_b = vector<int>(vec_a)) or other mystery way?
A b=a;
Is not assignment, it is called as Copy Initialization.
The implicitly generated copy constructor is called to create an new object b from the existing object a.
The implicitly generated copy constructor makes a copy of the array member.
For completeness I am going to add here the standard citation from the marked duplicate.
C++03 Standard: 12.8 (Copying class objects)
Each subobject is copied in the manner appropriate to its type:
if the subobject is of class type, the copy constructor for the class is used;
if the subobject is an array, each element is copied, in the manner appropriate to the element type;
if the subobject is of scalar type, the built-in assignment operator is used.
If the members have copy constructors, they get invoked. If not, the default copy constructor does the equivalent of memcpy. See Memberwise Assignment and Initialization.
In the case of non-pointer arrays, each element is copied.