Lets say I have this class:
class X {
public:
int x;
};
I saw that if I create an instance of X locally, x will not be initialize to 0, only if I create it globally.
Does this mean that the default constructor isn't synthesized by the compiler(I doubt it) for objects created localy or it will be synthesized but not zero out x value, if this is the case why is that ?
Constructors in C++ don't generally initialize members to 0. You have to explicitly initialize members with a value.
The reason that in the global case the memory is zero, is because static memory gets initialized to zero before anything else happens to it. In your case, the implicitly generated default constructor gets called afterwards, which does not touch the memory for member X.
See also this answer from Derek: Is global memory initialized in C++?
Note, however, that default constructors for structured, non-POD members (classes and structs) do automatically get called by the default constructor. It's just the POD members that are left alone by default.
X gets a synthesised constructor, but synthesised constructors do not zero-initialise primitives.
You are combining the concept of object construction with member initialization. As a general rule, don't expect C++ to initialize primitive data members for you, you'll need to do that yourself (preferably via an initialization list after the constructor.)
This is primarily for speed, as this allows allocation without initialization, which is useful if, for instance, you will be computing the values of the data members later and overwriting any "default" values.
I've found this site a useful reference in the past: http://www.cplusplus.com/doc/tutorial/variables/
Default constructors are not aware that it should initialize your member variables. If you need to initialize x to something, you better add your own constructor to do this for you:
class X {
public:
X() : x(0) { };
int x;
};
Related
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.
#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).
From Thinking in C++
The first hidden argument to the constructor is the this pointer. this pointer holds the address of the caller object. In the case of constructor this pointer points towards an uninitialized block of memory. It is the job of the constructor to initialize this block of memory properly.
So, basically, the constructor is used to get a pointer to the object's space in RAM? Is that correct?
How does the default constructor initialize that memory? Does it get initialized to zero?
The role of the default constructor is the same as any other constructor: To initialize the object. The default constructor (or a constructor with only default arguments) sets member variables to a known state, like setting pointers to nullptr (or 0), etc.
Lets say we have this structure:
struct Foo
{
int a;
int* b;
// Default constructor
// Set `a` to `1`, and `b` to `nullptr`
Foo() : a(1), b(nullptr) {}
};
Now when you declare an instance of the Foo class, then you know what state the member variables will have. If there wasn't a constructor, a normal local variable instance of the Foo class would have undefined values for the a and b members.
If you don't provide a constructor at all, default or other, then the compiler will make a default constructor for you (one is needed, or you would not be able to create instances of the classes), but it will not do any initialization of members.
The hidden argument talked about, is the variable known as this, and it exists for all member functions which are not static.
So, basically, the constructor is used to get a pointer to the object's space in RAM? Is that correct?
No, the constructor is not used to get a pointer.
The purpose of the constructor is to initialize all member variables when an object of this class is created. It initializes the object in memory.
The default constructor is the constructor that can be called with no arguments.
When you implement a class, you can implement your own default constructor to make it do what you want it to do.
When you do not provide any constructor for your class, the compiler will provide a default constructor for this class, but it will not initialize the members.
Default constructors are significant because they are automatically invoked in certain circumstances:
When an object value is declared with no argument list, e.g. MyClass x;; or allocated dynamically with no argument list, e.g. new MyClass or new MyClass(); the default constructor is used to initialize the object
When an array of objects is declared, e.g. MyClass x[10]; or allocated dynamically, e.g. new MyClass [10]; the default constructor is used to initialize all the elements
When a derived class constructor does not explicitly call the base class constructor in its initializer list, the default constructor for the base class is called
When a class constructor does not explicitly call the constructor of one of its object-valued fields in its initializer list, the default constructor for the field's class is called
In the standard library, certain containers "fill in" values using the default constructor when the value is not given explicitly, e.g. vector<MyClass>(10); initializes the vector with 10 elements, which are filled with the default-constructed value of our type.
In the above circumstances, it is an error if the class does not have a default constructor.
No. The constructor is not used to get a pointer. The constructor receives this pointer.
The constructor is used to initialize the object's space in RAM.
The default constructor does what you want it to do! I mean your can write your own default constructor for your class. This default constructor can initialize the memory, or leave it uninitialized, as you choose.
In the same vein, the implicit default constructor will be written automatically by the compiler to initialize the object RAM space. It will take care of initializing the non-static member variables of your class that do have default constructors. For example, if your class has a non-static std::string as member variable, then std::string default constructor will be called to initialize this variable. All non-static member variables of POD types (int, char, pointers,...) will not be initialized.
No.
MyClass obj; // Default construct
MyClass* obj2 = new MyClass; // Also default construct
In the first one, space for obj is first allocated, typically in the stack. The second one is allocated on the heap. The addresses where they reside are the ones that are passed to the proper constructor in these case.
The first-argument-is-the-this-pointer situation does not only apply to the default constructor, as a hidden this pointer is passed to all non-static class methods as their first arguments[1].
Then you probably know the rest. The constructor sets-up and initializes the object's members and states and any other things that needs to be done.
[1]Have you observed some examples like this?
my_type obj;
func_that_calls_a_callback(std::bind(&my_type::method, &obj));
That demonstrates that the first parameter is a pointer to some object is bound to the first parameter of my_type::method. That becomes the this pointer which points, in this case, to obj.
So, basically, the constructor is used to get a pointer to the object's space in RAM? Is that correct?
No, that's just a consequence
How does the default constructor initialize that memory? Does it get initialized to zero?"
No: the default constructor is just a function. It does what what you define it to do.
It is normally designed to "initialize" the memory by assigning to the contained variables (the object member) a proper value or by calling in turn their own constructors.
Think to this:
class point
{
public:
int x,y; //< just two values
point() //< default constructor
{ x=0; y=0; } //< function body assigning values
};
or
class point
{
public:
int x,y; //< just two values
point() //< default constructor
:x(), y() //< member init-list explicitly calling contrutors
{} //< empty body
};
Note that, until you don't declare a variable of type point nothing will be executed.
int main()
{
point p; //< p created and point::point() called using p as *this
p.x=5; //< x member of p changed
return 0; //just exit main (jumps to the closing } )
} //< p destructor called here, using p as *this.
As per the "implicit default constructor", what it does is just:
call the bases implicit default constuctors
call the members implicit
default contructors.
For all class-based types, decaring a default ctor in fact replaces the implicit one, but -for "built-in types" (like int, char, float etc.)- the default explicit constructor -in fact- sets the value to zero, but the implicit one does nothing, thus letting the value uninitialized. (the implementations can use different techniques to come to this same result)
why does creation of an object needs a constructor?
Even if I don't define a constructor a default constructor is generated ..but why a constructor necessary?
why can't objects be created without a constructor?
This is more of a discussion on terminology than a real argument about the behavior. As you mention, in some cases there is nothing to be done during construction, so there should be no need for a constructor, right? Well, there is the concept of a trivial-constructor which is a constructor that does not do anything at all. For the sake of the standard document, it is easier to treat everything as having a (possibly trivial) constructor than to have to provide all the cases and exceptions in all places where it currently just states 'constructor'.
Consider that every use of 'constructor' would have to be replaced by 'constructor or nothing if the type does not have any virtual functions or bases and no members that require the generation of a constructor'.
This is the same reason why all virtual functions are called overrider even the first one in the hierarchy that by definition does not override anything. This form of generalization makes the language slightly easier to interpret, although not too many people will claim that section 8.5 on initialization is simple...
Also note that, while all user defined types by definition have a constructor, the constructor is not required for the creation of objects. In particular for objects with trivial-constructor the lifetime starts when the memory for the object is allocated (the standard, knowing that trivial means nothing to be done does not even go through the hop of requiring that the constructor is run in that case.
3.8 [basic.life]/1
The lifetime of an object is a runtime property of the object. An object is said to have non-trivial initialization if it is of a class or aggregate type and it or one of its members is initialized by a constructor other than a trivial default constructor. [ Note: initialization by a trivial copy/move constructor is non-trivial initialization. — end note ] The lifetime of an object of type T begins when:
-- storage with the proper alignment and size for type T is obtained, and
-- if the object has non-trivial initialization, its initialization is complete.
That second bullet used to read (C++03): if T is a class type with a non-trivial constructor (12.1), the constructor call has completed. Which more clearly stated that the constructor need not be executed. But the new wording expresses the intent in basically the same way. Only if the object has non-trivial initialization, the initialization needs to complete. For objects with trivial-constructor (trivial initialization) allocating the storage creates the object. Where does it matter?
struct T { int x; }; // implicitly defined trivial-constructor
T *p = static_cast<T*>(malloc(sizeof *p));
// *p is alive at this point, no need to do
T *q;
{ void *tmp = malloc(sizeof T);
q = new (tmp) T; // call constructor
}
In a way, this is a slightly philosophical question. You can think of a constructor as a subroutine that turns some uninitialized memory into an object. Or you can think of it as a language feature that makes initialization easier to follow, write, and understand. You could even answer the question circularly: why does creation of an object needs a constructor? Because that's what creation of an object is, in a sense. If you don't have a constructor, what you're creating isn't an object.
It may be that a particular constructor does nothing, but that's an implementation detail of that class. The fact that every class has a constructor means that the class encapsulates what initialization is necessary: to use the class safely, you don't need to know whether the constructor does anything. In fact, in the presence of inheritance, vtables, debug-tracking, and other compiler features, you might not even know whether the constructor does anything. (C++ complicates this slightly by calling some classes POD types, but the encapsulation holds as long as you don't need to know that something is of POD type.)
The invocation of a constructor defines the point at which an object is created. In terms of language semantics, when the constructor finishes, the constructed object exists: before that, the object does not exist, and it is an error to use it as if it did. This is why construction order (that is, the order that member object and base class sub-object constructors are called) is so important in C++ and similar languages: if your constructor can throw an exception, it's necessary to destroy exactly those objects that have been constructed.
To end up with a working program, the programmer, anyone who tries to understand the source code, the compiler and linker, the runtime library, and any other compilation tools, all need to have a shared idea of what the program means: the semantics of the program. Agreeing on the lifetime of an object—when the compiler can run extra code to help create it, and when you can safely use it—is actually a big part of this agreement. Constructors and destructors are part of defining this lifetime. Even if they happen to be empty sometimes, they provide a way for us to agree when an object is valid, thus making it easier (possible) to specify and understand the language.
Say you have a simple class :
class Foo
{
int bar;
}
What is the value of bar exactly? Maybe you don't care when your object gets its memory allocated, but the machine running your program needs to give it some value. That's what the constructor is for : initializing class members to some value.
Constructor is necessary to call the constructors on class members, except built-in types see
Parametrized Constructors can take arguments. For example:
class example
{
int p, q;
public:
example();
example(int a, int b); //parameterized constructor
};
example :: example()
{
}
example :: example(int a, int b)
{
p = a;
q = b;
}
When an object is declared in a parameterized constructor, the initial values have to be passed as arguments to the constructor function. The normal way of object declaration may not work. The constructors can be called explicitly or implicitly. The method of calling the constructor implicitly is also called the shorthand method.
example e = example(0, 50); //explicit call
example e(0, 50); //implicit call
This is particularly useful to provide initial values to the object.
Also you will find important stuff on this page :
http://en.wikipedia.org/wiki/Constructor_%28object-oriented_programming%29
I'm self studying C++.
If you're making a Class which only has a member variable that is a collection of "X" objects, (whatever X may be) would having just a default constructor and a deconstructor be enough seems its purely dealing with a collection of objects? Thanks.
EDIT: Sorry should have been clearer. For a different example, if you have a class "Aclass" that has an int, a string and a vector of objects of another class, would you advise the "Aclass" class to have a constructor with parameters? ie Aclass(int i, string s); and do you need to have the vector in the constructor too? I'm a little confused. Thanks.
If by "collection of 'x' objects" you mean "a standard container of 'x' objects", and by "enough" you mean "enough not to worry about resource management" then yes. Same goes for any well-written container made by you or a third-party.
This is also assuming your X objects are handling their resources correctly. And that they have semantics that are compatible with the container you're putting them in.
Edit
You don't need a constructor like that if you are OK having an object filled with default values for everything. I.e. empty containers, zeroed members (or was it uninitialized? -_-), etc.
You only really need a custom constructor if your object will be in an invalid state without one or if you want some sort of custom logic to run.
You mean enough to handle memory correctly? Depends on the type X. For example, if you have a vector<string> data member, you don't have to do any manual memory management in your class.
For class you may write your own constructor, which shows, how to construct inner objects, i.e
class A{
string s;
int x;
A(string t):s(t), x(17){} // x is always 17 after construction
}
But if inner object is default-constructable, you may leave it's construction and it will be costruct by default.
A(int l):x(l){}
is equivalent to
A(int l):x(l), s(){}
(except for primitive types), that may contain trash by default
If you use default constructor of A, all inner objects will construct by default.
If by collection you mean standard library classes, you would need copy ctor and assignment operator= overloaded.
std::map and std::set would reqire an additional comparison operator< overloaded.
std::unorderd_map and std::unordered_set would need a std::hash specialized for your type.
Often you don't have to define a default constructor. The compiler will declare a default constructor implicitly if one is needed and no constructors are defined. Often it will be useful to define additional constructors (like the one you mention) in addition to the default one. In that case you need to define both:
class A
{
public:
string s;
int x;
// default constructor, no arguments
A(): x(), s() {}
// constructor
A(int i, string t): x(i), s(t) {}
}
int main()
{
A a1;
A a2(5, "text");
vector<A> ls;
return 0;
}
As pwned mentions, in order to use your class A in an STL container, e.g. vector, it is required that A has a default constructor as in the example (either user-defined or implicit).