What happens when you define an empty default constructor? - c++

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.

Related

Is a constructor implicitly declared in the case of a abstract class with no data members? [duplicate]

In the book I'm reading at the moment (C++ Without Fear) it says that if you don't declare a default constructor for a class, the compiler supplies one for you, which "zeroes out each data member". I've experimented with this, and I'm not seeing any zeroing -out behaviour. I also can't find anything that mentions this on Google. Is this just an error or a quirk of a specific compiler?
If you do not define a constructor, the compiler will define a default constructor for you.
Construction
The implementation of this
default constructor is:
default construct the base class (if the base class does not have a default constructor, this is a compilation failure)
default construct each member variable in the order of declaration. (If a member does not have a default constructor, this is a compilation failure).
Note:
The POD data (int,float,pointer, etc.) do not have an explicit constructor but the default action is to do nothing (in the vane of C++ philosophy; we do not want to pay for something unless we explicitly ask for it).
Copy
If no destructor/copy Constructor/Copy Assignment operator is defined the compiler builds one of those for you (so a class always has a destructor/Copy Constructor/Assignment Operator (unless you cheat and explicitly declare one but don't define it)).
The default implementation is:
Destructor:
If user-defined destructor is defined, execute the code provided.
Call the destructor of each member in reverse order of declaration
Call the destructor of the base class.
Copy Constructor:
Call the Base class Copy Constructor.
Call the copy constructor for each member variable in the order of declaration.
Copy Assignment Operator:
Call the base class assignment operator
Call the copy assignment operator of each member variable in the order of declaration.
Return a reference to this.
Note Copy Construction/Assignment operator of POD Data is just copying the data (Hence the shallow copy problem associated with RAW pointers).
Move
If no destructor/copy Constructor/Copy Assignment/Move Constructor/Move Assignment operator is defined the compiler builds the move operators for you one of those for you.
The default implementation is:
Implicitly-declared move constructor
If no user-defined move constructors are provided for a class type (struct, class, or union), and all of the following is true:
Move Constructor:
Call the Base class Copy Constructor.
Call the move constructor for each member variable in the order of declaration.
Move Assignment Operator:
Call the base class assignment operator
Call the move assignment operator of each member variable in the order of declaration.
Return a reference to this.
I think it's worth pointing out that the default constructor will only be created by the compiler if you provide no constructor whatsoever. That means if you only provide one constructor that takes an argument, the compiler will not create the default no-arg constructor for you.
The zeroing-out behavior that your book talks about is probably specific to a particular compiler. I've always assumed that it can vary and that you should explicitly initialize any data members.
Does the compiler automatically generate a default constructor?
Does the implicitly generated default constructor perform zero
initialization?
If you legalistically parse the language of the 2003 standard, then the answers are yes, and no. However, this isn't the whole story because unlike a user-defined default constructor, an implicitly defined default constructor is not always used when creating an object from scratch -- there are two other scenarios: no construction and member-wise value-initialization.
The "no construction" case is really just a technicality because it is functionally no different than calling the trivial default constructor. The other case is more interesting: member-wise value-initialization is invoked by using "()" [as if explicitly invoking a constructor that has no arguments] and it bypasses what is technically referred to as the default constructor. Instead it recursively performs value-initialization on each data member, and for primitive data types, this ultimately resolves to zero-initialization.
So in effect, the compiler provides two different implicitly defined default constructors. One of which does perform zero initialization of primitive member data and the other of which does not. Here are some examples of how you can invoke each type of constructor:
MyClass a; // default-construction or no construction
MyClass b = MyClass(); // member-wise value-initialization
and
new MyClass; // default-construction or no construction
new MyClass(); // member-wise value-initialization
Note: If a user-declared default constructor does exist, then member-wise value-initialization simply calls that and stops.
Here's a somewhat detailed breakdown of what the standard says about this...
If you don't declare a constructor, the compiler implicitly creates a default constructor [12.1-5]
The default constructor does not initialize primitive types [12.1-7]
MyClass() {} // implicitly defined constructor
If you initialize an object with "()", this does not directly invoke the default constructor. Instead, it instigates a long sequence of rules called value-initialization [8.5-7]
The net effect of value initialization is that the implicitly declared default constructor is never called. Instead, a recursive member-wise value initialization is invoked which will ultimately zero-initialize any primitive members and calls the default constructor on any members which have a user-declared constructor [8.5-5]
Value-initialization applies even to primitive types -- they will be zero-initialized. [8.5-5]
int a = int(); // equivalent to int a = 0;
All of this is really moot for most purposes. The writer of a class cannot generally assume that data members will be zeroed out during an implicit initialization sequence -- so any self-managing class should define its own constructor if it has any primitive data members that require initialization.
So when does this matter?
There may be circumstances where generic code wants to force initialization of unknown types. Value-initialization provides a way to do this. Just remember that implicit zero-initialization does not occur if the user has provided a constructor.
By default, data contained by std::vector is value-initialized. This can prevent memory debuggers from identifying logic errors associated with otherwise uninitialized memory buffers.
vector::resize( size_type sz, T c=T() ); // default c is "value-initialized"
Entire arrays of primitives type or "plain-old-data" (POD)-type structures can be zero-initialized by using value-initialization syntax.
new int[100]();
This post has more details about variations between versions of the standard, and it also notes a case where the standard is applied differently in major compilers.
C++ does generate a default constructor but only if you don't provide one of your own. The standard says nothing about zeroing out data members. By default when you first construct any object, they're undefined.
This might be confusing because most of the C++ primitive types DO have default "constructors" that init them to zero (int(), bool(), double(), long(), etc.), but the compiler doesn't call them to init POD members like it does for object members.
It's worth noting that the STL does use these constructors to default-construct the contents of containers that hold primitive types. You can take a look at this question for more details on how things in STL containers get inited.
The default constructor created for a class will not initialize built-in types, but it will call the default constructor on all user-defined members:
class Foo
{
public:
int x;
Foo() : x(1) {}
};
class Bar
{
public:
int y;
Foo f;
Foo *fp;
};
int main()
{
Bar b1;
ASSERT(b1.f.x == 1);
// We know nothing about what b1.y is set to, or what b1.fp is set to.
// The class members' initialization parallels normal stack initialization.
int y;
Foo f;
Foo *fp;
ASSERT(f.x == 1);
// We know nothing about what y is set to, or what fp is set to.
}
The compiler will generate default constructors and destructors if user-created ones are not present. These will NOT modify the state of any data members.
In C++ (and C) the contents of any allocated data is not guaranteed. In debug configurations some platforms will set this to a known value (e.g. 0xFEFEFEFE) to help identify bugs, but this should not be relied upon.
Zero-ing out only occurs for globals. So if your object is declared in the global scope, its members will be zero-ed out:
class Blah
{
public:
int x;
int y;
};
Blah global;
int main(int argc, char **argv) {
Blah local;
cout<<global.x<<endl; // will be 0
cout<<local.x<<endl; // will be random
}
C++ does not guarantee zeroing out memory. Java and C# do (in a manner of speaking).
Some compilers might, but don't depend on that.
In C++11, a default constructor generated by the compiler is marked deleted , if :
the class has a reference field
or a const field without a user-defined default constructor
or a field without a default initializer, with a deleted default constructor
http://en.cppreference.com/w/cpp/language/default_constructor
C++ generates a default constructor. If needed (determined at compile time I believe), it will also generate a default copy constructor and a default assignment constructor. I haven't heard anything about guarantees for zeroing memory though.
The compiler by default will not be generating the default constructor unless the implementation does not require one .
So , basically the constructor has to be a non-trivial constructor.
For constructor to be non-trivial constructor, following are the conditions in which any one can suffice:
1) The class has a virtual member function.
2) Class member sub-objects or base classes have non-trivial constructors.
3) A class has virtual inheritance hierarchy.

does POD class object initialization require constructor?

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.

why do I need a constructor function?

#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).

C++ Adding objects that have constructors to an array

When I declare a an array, all the variables/objects get declared. But what happens with the objects, if their class has constructors? The class I'm using has 2 constructors - one with no arguments and one with a few arguments. Will the first constructor activate after the declaration? Or no constructors will activate?
If the first case happens, I'll have to make a function that replaces the constructors.
So, what happens with the objects in a newly declared array?
It depends how you declare the array. The members will be either default, value, or copy-initialized:
Foo x[] = { Foo(1), Foo(true, 'a'), Foo() }; // copy-initialize
Foo x[3] = { }; // value-initialize
Foo x[3]; // default-initialize
For class types, default- and value-initialization call the default constructor. Copy-initialization may call the appropriate constructor directly.
If you don't want to use the default-constructor, you won't get arround the brace-initializer and spelling out each member.
Arrays will invoke the default constructors on all objects if the underlying type has a non-trivial default constructor.
I don't remember the rules exactly, but ints, char*s, structs whose members all have trivial constructors, etc., all have trivial default constructors. Arrays of these things (and arrays of arrays of these things, etc.) won't be initialised unless you do so explicitly.
An explicitly declared default constructor is never trivial, so the Foo objects in your array will be default-constructed.

Difference between A* pA = new A; and A* pA = new A();

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.