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.
Related
Consider the simple struct below (defaulted just to be explicit).
struct foo {
foo() = default;
foo(const foo&) = default;
};
foo bar() {
return foo{}; // return does copy init
}
What kind of initializations take place below?
foo a; // default init
foo b{}; // value initialization
foo c{bar()}; // ?? mandatory copy elision. is this considered direct init? so copy init to return from
// bar(), then direct init to init c?
foo d{c}; // ?? copy constructor called. is this considered direct init or copy init?
foo e = d; // copy init
Looking for answers for C++ 17. Please provide references whenever applicable.
Thanks.
Given foo c{bar()};, c is direct-list-initialized from the return value of bar(). And it's same for foo d{c};, d is direct-list-initialized from c.
initialization of a named variable with a braced-init-list (that is, a possibly empty brace-enclosed list of expressions or nested braced-init-lists)
As the effect, for foo c{bar()};, because of mandatory copy elision (since C++17) the copy construction in the return statement and the initialization of c are omitted, c is constructed by the default constructor directly. For foo d{c};, the copy constructor is selected to construct d.
BTW: In bar(), return foo{}; performs copy initialization, because of mandatory copy elision (since C++17) the copy construction is omitted, the return value is initialized by the default constructor directly (since C++20). (Until C++20 it'll be aggregate-initialized.)
What Type of Initialization Occurs When Calling Copy Constructor?
Your question is backwards and ultimately unanswerable.
Initialization forms determine the various steps used to take the initializer expressions and initialize an object from them. There are many forms of initialization, and most of them have some mechanism that can ultimately lead to a copy constructor call. List initialization, direct initialization, copy initialization, aggregate initialization, all of these could call the copy constructor, given the right initializer, of course.
As such, you cannot know which initialization form was used solely from the fact that a copy constructor was called.
The form of initialization used is determined by the syntax that initializes the object.
foo c{bar()};
foo d{c};
These use the same initialization syntax, so they use the same form of initialization. This is direct-initialization, but because the initializer is a braced-init-list ({}), that will quickly become direct-list-initialization.
foo e = d;
This syntax invokes copy initialization.
I recently ran into a problem with one of my classes because I hadn't set a pointer to NULL in my constructor initialiser list and so it contained rubbish when I ran the program.
However, whilst I know that instances of a built-in type declared on the stack but not initialised will contain random values, I was pretty sure I'd read somewhere that as class members not placed explicitly in the constructor initialiser list would have their default constructors called, for built-in types this would occur too, inserting code like a pseudo-constructor that will on most platforms, set them to zero I also thought I'd read in 'Thinking in C++' somewhere that under certain circumstances before an object is constructed its memory will be zeroed-out, however I appear to be wrong on both occasions.
Please could anyone confirm for me,
a) Does initialisation of members of a built-in type have anything to do with whether a user-defined constructor is defined or not,
b) do members of a built-in type always need to be initialised manually, and
c) are there any circumstances under which an object's storage is zeroed-out before the constructor is called?
Also, in researching this, I have seen the terms 'default-initialised' and 'zero-initialised' used - is there a difference between saying:
T a;
and
T a();
? I thought that the first form was just used to prevent ambiguity when the second may be taken by the compiler as a function declaration.
Thank you very much for your time,
stellarpower
First let's go over some examples and the correct terminology.
T a1; // default initialization
T a2{}; // value initialization
T(); // also value initialization
new T; // default initialization
new T(); // value initialization
new T{}; // also value initialization
class C1 {
C1() {}
T x;
}; // no initializer for C1::x; default-initialized
class C2 {
T x;
}; // implicit default constructor default-initializes C2::x
class C3 {
C3() : x() {}
T x;
}; // C3::x will be value-initialized.
class C4 {
C4() : x{} {}
T x;
}; // C4::x will also be value-initialized.
// DANGER
T a(); // declares a function; not value initialization (quirk of C++)
Generally, the rule is that when there is no initializer, it is default initialization, and when the initializer is () or {}, it is value initialization. Note that there is an exception for statics and thread-locals, which I'll discuss later.
For an integer or floating-point type, value initialization sets it to 0. For a pointer type, value initialization sets it to null. Default initialization does nothing for scalar types. Therefore, if an object of scalar type only receives default initialization, then it has indeterminate value.
a) Does initialisation of members of a built-in type have anything to do with wheher a user-defined constructor is defined or not,
The default constructor for a class default-initializes members. A member is also default-initialized when no mem-initializer is explicitly provided for it. The examples C1 and C2 illustrate this. However, note that when a class type is value-initialized, and the class's default constructor is either implicitly defined or explicitly defaulted, the class's members will be zeroed out. This zeroing out occurs only in this case, and doesn't occur for a user-provided default constructor. So the answer to your question is "yes" in this sense.
C1 y1; // y1 is default-initialized; y1.x is indeterminate
C1 y2{}; // y2 is value-initialized; y2.x is indeterminate
C2 y3; // y3 is default-initialized; y3.x is indeterminate
C2 y4{}; // y4 is value-initialized; y4.x is set to 0
C3 y5; // y5 is default-initialized; y5.x is set to 0
C3 y6{}; // y6 is value-initialized; y6.x is set to 0
b) do members of a built-in type always need to be initialised manually, and c) are there any circumstances under which an object's storage is zeroed-out before the constructor is called?
I assume you mean "class members with built-in type". I covered a case above in which they are automatically initialized to 0: where the class object is value-initialized and its constructor is not user-provided (or deleted). Another case is when the class object has static or thread-local storage duration. In this case, the members will also be zeroed out at the very beginning, so there is no chance of them ending up with indeterminate value.
The term you are looking for is default initialized. Any instance data member will be default initialized if it is not explicitly initialized in the body of the constructor. What this means depends on whether the data member is a primitive data type or not and where the object instantiation takes place. In case of data members of non-primitive data types, the default constructor will be used (or the compiler will complain if there is no default constructor). In case of data members of primitive data types this means that they will not be initialized if the instantiation takes place on the stack or on the heap. If it is a global or a static variable however, the data members will be set to 0.
By the way, when you write
T a;
then you define a variable a of type T. When you write
T a();
then you declare a function a() which returns T by value.
One way to default initialize all member variables without calling a constructor would be if you have a POD type. For e.g. this is a POD
class Foo {
int num1;
double num2;
bool b;
int *pnum;
};
and if you do
Foo foo = {};
everything will be zero-initialized (b will be false, pnum NULL etc) without calling the (default) constructor.
So
a) a POD type must not have a user defined constructor so in that case yes
b) if you have a POD you don't have to initialize them manually
c) if you have a POD type you can zero-initialize without calling a constructor.
Another way to create a class instance and zero-initialize without calling a constructor would be to allocate the required memory with calloc and cast the pointer to the required type. You should avoid that unless absolutely necessary!
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.
#include<iostream>
using namespace std;
class A {
public:
int i;
};
int main() {
const A aa; //This is wrong, I can't compile it! The implicitly-defined constructor does not initialize ‘int A::i’
}
when I use
class A {
public:
A() {}
int i;
};
this is ok! I can compile it! why I can't compile it when I use the implicitly-defined constructor?
why the implicit-defined constructor does not work?
It does work, but one of the language rules is that it can't be used to initialise a const object unless it initialises all the members; and it doesn't initialise members with trivial types like int. That usually makes sense, since being const there's no way to give them a value later.
(That's a slight simplification; see the comments for chapter and verse from the language standard.)
If you define your own constructor, then you're saying that you know what you're doing and don't want that member initialised. The compiler will let you use that even for a const object.
If you want to set it to zero, then you could value-initialise the object:
const A aa {}; // C++11 or later
const A aa = A(); // historic C++
If you want to set it to another value, or set it to zero without the user having to specify value-initialisation, then you'll need a constructor that initialises the member:
A() : i(whatever) {}
why the implicit-defined constructor does not work?
Because the C++ standard says so:
[dcl.init] paragraph 7:
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.
This ensures that you don't create a const object containing uninitialized data that cannot be initialized later.
To initialize a const-qualified object you need to have a user-provided default constructor or use an initialiser:
const A aa = A();
Here the object aa is initialized with the expression A() which is a value-initialized object. You can value-initialize a class type without a default constructor, because value-initialization will set values to zero if there is no default constructor for the type.
However, the rule in the standard is too strict, as it forbids using implicitly-defined constructors even when there are no data members or all data members have sensible default constructors, so there is a defect report against the standard proposing to change it, see issue 253.
You don't state what compiler you're using. I've tried this with VS2012 and get a warning C4269.
The reason this is a problem is because aa is const. Because you haven't defined a constructor a default one is used and so i can be anything. It also cannot be changed (because aa is const).
If you define a constructor, it is assumed that you are happy with the initialization of i. Although, in this case you haven't actually changed the behaviour.
From this MSDN page
Since this instance of the class is generated on the stack, the initial value of m_data can be anything. Also, since it is a const instance, the value of m_data can never be changed.
Because i is not initialized.
class A
{
public:
A()
{
i =0;
}
int i;
};
"Implicit constructor" means a constructor generated for you automatically and generates an error because it realizes it is not able to initialize the value of i. This can be a no-args constructor, a copy constructor or (as of C++11) a move constructor.
why the implicit-defined constructor does not work?
It works just fine, but it does not decide what your default values are implicitly (and as such, it only calls default constructors for it's members, but not for POD types).
If you want the constructor to initialize your members with certain values you have to explicitly write that (i.e. add a default constructor explicitly).
Making a default (implicit) constructor initialize POD members with a chosen value (like zero for example) would add extra computing cycles (and slow your program down) when you don't need that. C++ is designed to behave as if you (the programmer) know what you are doing (i.e. if you do not initialize your members explicitly, the compiler assumes you don't care what default value you get).
in C++, what is the exact difference between both following dynamic object creations :
A* pA = new A;
A* pA = new A();
I did some tests, but it seems that in both cases, the default constructor is called and only it. I'm looking for any difference about performance...
Thanks
If A is a POD-type, then new A will allocate a new A object but leave it with an indeterminate value, otherwise new A will default initialize the new object.
In all cases new A() will value initialize the new A object.
This is obviously different behaviour for POD types but also affects non-POD, non-union class types without a used-declared constructor.
E.g.
struct A
{
int a;
std::string s;
};
A is a non-POD class type without a user-declared constructor. When an A is default initialized the implicitly defined constructor is called which calls the default constructor for s (a non-POD type), but a is not initialized.
When an A is value initialized, as it has no used-declared constructor, all of its members are value initialized which means that the default constructor for s is called and a is zero initialized.
ISO 14882:2003 references:
5.3.4 [expr.new]/15: How objects allocated by a new expression are initialized depending on whether the initializer is omitted, a pair of parentheses or otherwise.
8.5 [dcl.init]/5: The meaning of zero initialize, default initialize and value initialize.
12.1 [class.ctor]/7,8: The form of a user-written constructor that matches the behaviour of an implicitly defined default constructor.
12.6.2 [class.base.init]/4: How bases and members which are not listed in a member initializer list of a constructor are initialized.
It's exactly the same, also performance wise :)
The lexer will have to scan two characters less in the first version, so the compilation process is a little faster ;)
please see STL implementing code (e.g. allocator) then you'll understand.