I saw this in a textbook, but the book doesn't explain what it actually does, and why I should do this. Here is something similar to the example in the book:
class MyClass
{
public:
MyClass(int initial_capacity = 20);
private:
int capacity;
}
I can't use initial_capacity in the implementation, I can't even implement anything, so I am confused as to what this is for? Does it set capacity to 20 somehow? How is this a default constructor?
Probably, there is missed implementation of constructor. For example, if constructor looks like this one :
MyClass(int initial_capacity = 20) {
capacity = initial_capacity;
}
If you create object this way:
MyClass a(10);
capacity will be set to 10.
On the other hand, if you will create object like this:
MyClass a;
capacity will be set to 20.
This is a constructor with a default parameter. It means that you can either call it with a number, or without a number. If you call it without a number, it is the same as if you called with the number 20.
MyClass(int initial_capacity = 20);
This syntax provides a default value for the initial_capacity parameter. Note that you can do this with parameters for any function, not just with constructors. Default parameter values are helpful because it allows you to do both
MyClass c(5);
and
MyClass c;
In the later, the default value is used.
It serves as a default value for initial_capacity if the user chooses not to put in a value. So in essence it takes the place of 2 constructors: one that takes an integer MyClass(int); and one that doesn't take any parameters MyClass(); which will be 20.
Assuming that you are going to use that to set a value to capacity, there are two ways to use it . . .
either in your .cpp file
#include "<...>.h"
MyClass::MyClass(int initial_capacity)
{
capacity = initial_capacity;
}
or you can elect to do it straight from your .h file
class MyClass
{
public:
MyClass(int initial_capacity = 20)
: capacity(initial_capacity) // member initialization list
{}
private:
int capacity;
};
This shorthand which is preceded by the semicolon is called a member initialization list.
Be aware though, that calling it this way may get you into trouble because it will automatically create a parameterless constructor for you.
Related
Regarding the following, are there any reasons to do one over the other or are they roughly equivalent?
class Something
{
int m_a = 0;
};
vs
class Something
{
int m_a;
Something(int p_a);
};
Something::Something(int p_a):m_a(p_a){ ... };
The two code snippets you posted are not quite equal.
class Something
{
int m_a = 0;
};
Here you specify the value with which to initialise, i.e. 0, at compile time.
class Something
{
int m_a;
Something(int p_a);
};
Something::Something(int p_a):m_a(p_a){ ... };
And here you do it at run time (or possibly at run time), with the value p_a not known until the constructor is called.
The following piece of code comes closer to your first example:
class Something
{
int m_a;
Something();
};
Something::Something() : m_a(0) { /* ... */ };
What you have to consider here is that in the first case, the value appears directly in the class definition. This may create an unnecessary dependency. What happens if you need to change your 0 to 1 later on? Exposing the value directly in the class definition (and thus, usually, in a header file) may cause recompilation of a lot of code in situations where the other form of initialisation would avoid it, because the Something::Something() : m_a(0) part will be neatly encapsulated in a source file and not appear in a header file:
// Something.h - stable header file, never changed
class Something
{
int m_a;
Something();
};
// Something.cpp - can change easily
Something::Something() : m_a(0) { /* ... */ };
Of course, the benefits of in-class initialisation may vastly outweigh this drawback. It depends. You just have to keep it in mind.
The first form is more convenient if you have more than one constructor (and want them all to initialise the member in the same way), or if you don't otherwise need to write a constructor.
The second is required if the initialiser depends on constructor arguments, or is otherwise too complicated for in-class initialisation; and might be better if the constructor is complicated, to keep all the initialisation in one place. (And it's also needed if you have to support pre-C++11 compilers.)
The first form is new to C++11 and so at this point isn't terribly well supported, especially if you need to support a variety of older compilers.
Otherwise they should be roughly equivalent when a C++11 compiler is available.
Elaborating on Christian Hackl's answer.
The first form allows to initialize m_a and have a default c'tor at the same time. Or you can even be explicit in your code and define a constructor with the default keyword:
class Something
{
int m_a = 0;
// explicitly tell the compiler to generate a default c'tor
Something() = default;
};
With the second form, an auto-generated default c'tor would leave m_a uninitialized, so if you want to initialize to a hard-coded value, you have to write your own default c'tor:
class Something
{
int m_a;
// implement your own default c'tor
Something() : m_a(0) {}
};
class Something
{
int m_a = 0;
};
is equivalent to
class Something
{
int m_a(0);
};
So, doing
class Something
{
int m_a;// (0) is moved to the constructor
public:
Something(): m_a(0){}
};
yields a uniform syntax for initialization that requires or does not require run-time input.
Personally I don't like the first form because it looks like an "declaration then assignment", which is complete misconception.
If you change the code like what Christian did to make them do the same thing. Now it is a tradeoff between compile-time optimization (which Christian explained completely) and run-time optimization.
class Foo{
public:
Vector<double> vec1;
.
.
.
Vector<double> vecN;
}
Imagine you have to initialize each vector by some predefined doubles. If the program must instantiate many and many objects of this class, it is better to initialize the vectors in the header file to make the user happy by reducing the run-time!
Even though it's supported, this type of initialization will create bugs that will be pretty hard to track down. It's the type of "aesthetic optimization" that you will regret a couple months down the road.
See the example below:
class_x_1.h:
class X
{
private:
int x = 10;
public:
int GetX();
};
class_x_2.h:
class X
{
private:
int x = 20;
public:
int GetX();
};
class_x.cpp:
#include "class_x_1.h" // implementation uses the version that initializes x with 10
int X::GetX()
{
return x;
}
main.cpp:
#include "class_x_2.h" // main includes definition that initializes x with 20
#include <iostream>
int main()
{
X x;
std::cout << x.GetX() << std::endl;
return 0;
}
Output:
20
As expected, it will return 20 because this is the version that initializes x with 20. However, if you go to the implementation of X, you might expected it to be 10.
What is the advantage (if one exists) to assigning a variable in the header of a function or constructor? In other words, what is the difference between the following two sets of code and why would I prefer one over the other?
Example 1:
class A {
private:
char* b;
public:
A(size_t var = 8*1024*1024) {
...
b = new char[var];
...
}
...
};
Example 2:
class A {
private:
char* b;
public:
A() {
const size_t var = 8*1024*1024;
...
b = new char[var];
...
}
...
};
I appreciate any constructive input.
That is a default argument. It allows the caller to call the function without passing an argument, in which case the default value is used.
So in the first example, one could call:
A* myADefault = new A(); // creates A with default value (8*1024*1024)
A* myLargerA = new A(16*1024*1024); // creates A passing 16*1024*1024 instead of the default
(for more info, look at the "Default values in parameters" section in this tutorial: http://www.cplusplus.com/doc/tutorial/functions2/)
It's really different.
The first represents a default value, that means you can declare A test or A test2(42). In test, b will have a size of 8*1024*1024. In test2, b will have a size of 42.
The second snippet is just a constante value.
You will prefere one to other depending on your needs ...
This is a so called default argument: http://msdn.microsoft.com/en-us/library/91563f79(v=vs.80).aspx
The difference is that you can set value for the the var in the first case but not in the second case.
What you've wrote are two different beings : in the first example, var is an input parameter with a default value of 8*1024*1024 while in the second, it is a local const variable. Even if the behaviour is the same, the inner structure isn't.
To anwser your question about the preference of one method over the other, it depends on your design : the former add some flexibility, but also expose a parameter which maybe should stay hidden, while the latter is more rigid, but also less error-prone.
But neither case is particularly good. Member variables should be initialized in constructor initialization lists. That is the only way to initialize a const member variable, for example.
class A {
private:
char* b;
public:
A(size_t var = 8*1024*1024): b(new char[var]) {
...
}
~A() {
delete [] b;
}
};
Even then, a smart pointer would be better for b.
I want to know what's difference in the following two class.
example 1:
class A
{
string name;
public:
A(const char* _name):name(_name){}
void print(){cout<<"A's name:"<<name<<endl;}
};
example 2:
class A
{
string name;
public:
A(const char* _name){name(_name);}
void print(){cout<<"A's name:"<<name<<endl;}}
why the example 1 is passed and the last one is wrong?
Thanks
In example 1 you initialize the string with the given value right away.
In example 2 you create an empty string first and assign it later on.
Despite some performance differences and ignoring possible differences due to copy constructor handling etc. it's essentially the same result.
However once you use a const member you'll have to use example 1's way to do it, e.g. I usually create unique IDs the following way:
class SomeObject
{
static unsigned int nextID = 0;
const unsigned int ID;
SomeObject() : ID(nextID++)
{
// you can't change ID here anymore due to it being const
}
}
The first example is an actual initialization. It has a number of advantages, including being the only way to set up const members, and having proper exception-safety.
The second example is not valid C++, AFAIK. If you had instead written name = name_, then this would just be normal assignment. Of course, this isn't always possible; the object might be const, or not have an assignment operator defined. This approach could also be less efficient that the first example, because the object is both default-initialized and assigned.
As for why the initializer list is before the constructor body; well, that's just the way the language has been defined.
That's just how the language is defined. The member initializers should be placed before the body of the constructor.
In the first example the member name is initialized with a ctr getting char * as parameter.
In the second case it is initialized with a default ctr at first and it gets value by the assignment operator (operator=) later. That's why it is wrong with your case that it is already constructed there so you can not use the ctr once again you could just use the assignment operator.
The reason is that name lookup works different in initializer lists and function bodies:
class A
{
std::string foo; // member name
public:
A(const char* foo) // argument name
: foo(foo) // member foo, followed by argument foo.
{
std::cout << foo; // argument foo.
}
};
If the initializer list was inside the function body, there would be an ambiguity between member foo and argument foo.
The motivation behind the initialization list is due to const field holding a object by value (as opposed to reference/pointer field).
Such fields must be initialized exactly once (due to their const-ness). If C++ didn't have initialization list then a ctor would look something like:
class A {
public:
const string s;
const string t;
A() {
// Access to either s or t is not allowed - they weren't initialized
s = "some-string";
// now you can access s but you can't access t
f(*this);
t = "some other string";
// From now you can access both ...
}
}
void f(A& a) {
// Can you access a.s or a.t?
cout << a.s << a.t;
}
Without an initialization list a ctor can pass a partially-initialized object of type A to a function, and that function will have no way of knowing which fields are initialized yet. Too risky and very difficult for the compiler/linker to check.
I've been programming in C++ a while and I've used both methods:
class Stuff {
public:
Stuff( int nr ) : n( nr ) { }
private:
int n;
}
Or
class Stuff {
public:
Stuff( int nr ) {
n = nr;
}
private:
int n;
}
Note: This is not the same as this, similar but not the same.
What is considered best practice?
Initializer lists are preferred. See FAQ 10.6
One big advantage to using initializers: If an exception is thrown anywhere within the initializer list, the destructors will be called for those members that had already been initialized -- and only for those members.
When you use the contructor body to initialize the object, it's up to you to handle exceptions properly and unwind the object as appropriate. This is usually much harder to get right.
Use the initializer list when possible. For an int, it doesn't matter much either way, but for a more complex member object, you'd end up with the default constructor of the object being called, followed by an assignment to that object, which is likely to end up being slower.
Plus, you have to do it that way anyway for const members or members which don't have a default constructor.
If possible, use the first version.
The first is initializing using intializer lists, and actually calls the constructors of the members.
The second is assignment. If n was of a type with a default constructor, it the would have already been called, and then you'd be assigning to it. If n didn't have a default constructor, you'd be forced to use the first type. Likewise if n was a reference: int &n.
If there are no constructors of you members that directly take one of the parameters to your constructor, it may be worthwhile to add private static functions that can do the conversion for you.
I generally try to do the initializer list when I can. For one thing, this makes it explicit that you are initializing code in the constructor. const memebers have to be initialized this way.
If you just put code in the constructor's body, it is quite possible someone may decide to come along and move a big chunk of it into a non-constructor "setup" routine later.
It can be taken overboard though. I have a coworker who likes to create classes that have 2 pages of initilizer code, no constructor code, and perhaps 2 pages for the entire rest of the class' code. I find that really tough to read.
I want to add that you don't need to declare the initializer list on the Header (.h). It can be done at the implementation of the constructor (which is very common).
So then:
//Stuff.h
class Stuff {
public:
Stuff( int nr );
private:
int n;
}
//Stuff.cpp
Stuff::Stuff(int nr)
: n(nr)
{
//initalize complex members
}
is legal and imo concentrates the initialization of fields where it matters. Sometimes we need to initialize complex members in the body, so you have your initializer list and the complex initialization all in the .cpp file.
The second option is not initialization but assignment. With types that have user defined default constructors, the second option will call the default constructor and later on call the assignment operator (whether user defined or not) to assign the value.
Some types cannot be default initialized: If you have an attribute without default constructor, hold references (constant or not) or have constant attributes they must be initialized in the initializer list.
Arrays can be value-initialized in the initialization list, but not in the constructor body:
class X {
public:
X() : array() {} // value-initializes the array
// equivalent to:
// X() { for ( int i = 0; i < 10; ++i ) array[i]=0; }
private:
int array[10];
};
For POD types, you can value-initialize them in the initialization list but not inside the brackets:
class X {
public:
X() : pod() {} // value-initializes
// equivalent to (but easier to read and subtly faster as it avoids the copy):
// X() { pod = {}; }
private:
PODType pod;
};
Finally, some classes offer functionality through the use of constructors that will be more complex (if achievable) after default construction.
class X
{
public:
X() : v(10) {} // construct a vector of 10 default initialized integers
// equivalent to:
// X() { for ( int i = 0; i < 10; ++i ) v.push_back(0); }
private:
std::vector<int> v;
};
Last, whenever they are in fact equivalent, initialization lists are more idiomatic in C++.
I'm reading this C++ open source code and I came to a constructor but I don't get it ( basically because I don't know C++ :P )
I understand C and Java very well.
TransparentObject::TransparentObject( int w, int x, int y, int z ) :
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
{
int bla;
int bla;
}
As far I can "deduce" The first line only declares the construtor name, the "::" sounds like "belongs to" to me. And the code between {} is the constructor body it self.
I "think" what's after the paremeters and the first "{" are like methods default parameters or something, but I don't find a reasonable explanation on the web. Most of the C++ constructors that I found in the examples are almost identical to those in Java.
I'm I right in my assumptions? "::" is like belongs to, and the list after params and body are like "default args" or something?
UPDATE:
Thanks for the answers.
May those be called methods? ( I guess no ) and what is the difference of call them within the constructor body
The most common case is this:
class foo{
private:
int x;
int y;
public:
foo(int _x, int _y) : x(_x), y(_y) {}
}
This will set x and y to the values that are given in _x and _y in the constructor parameters. This is often the best way to construct any objects that are declared as data members.
It is also possible that you were looking at constructor chaining:
class foo : public bar{
foo(int x, int y) : bar(x, y) {}
};
In this instance, the class's constructor will call the constructor of its base class and pass the values x and y.
To dissect the function even further:
TransparentObject::TransparentObject( int w, int x, int y, int z ) :
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
{
int bla;
int bla;
}
The ::-operator is called the scope resolution operator. It basically just indicates that TransparentObject is a member of TransparentObject. Secondly, you are correct in assuming that the body of the constructor occurs in the curly braces.
UPDATE: Thanks for the answers. May those be called methods? ( I guess no ) and what is the difference of call them within the constructor body
There is much more information on this subject than I could possibly ever give you here. The most common area where you have to use initializer lists is when you're initializing a reference or a const as these variables must be given a value immediately upon creation.
You are pretty close. The first line is the declaration. The label left of the :: is the class name and for it to be a constructor, the function name has to be the same as the class name.
TransparentObject::TransparentObject( int w, int x, int y, int z )
In C++ you can optionally put a colon and some initial values for member variables before the start of the function body. This technique must be used if you are initialzing any const variables or passing parameters to a superclass constructor.
:
_someMethod( 0 ),
_someOtherMethod( 0 ),
_someOtherOtherMethod( 0 ),
_someMethodX( 0 )
And then comes the body of the constructor in curly braces.
{
int bla;
int bla;
}
:: Actually means contains (see comments for clarification), however the _someMethods and so forth is what's called an initialisation list. There is plenty of info at the link =]
EDIT: Sorry, my first sentence is incorrect - see the comments.
Yes, :: is the C++ scoping operator which lets you tell the compiler what the function belongs to. Using a : after the constructor declaration starts what is called an initialization list.
The code between the argument list and the {}s specifies the initialization of (some of) the class members.
Initialization as opposed to assignment---they are different things---so these are all calls to constructors.
You're correct. Its a way to set the default values for the class variables. I'm not too familiar with the exact difference between putting them after : and in the function body.
There are usually some good reasons to use an initialization list. For one, you cannot set member variables that are references outside of the initialization list of the constructor. Also if a member variable needs certain arguments to its own constructor, you have to pass them in here. Compare this:
class A
{
public:
A();
private:
B _b;
C& _c;
};
A::A( C& someC )
{
_c = someC; // this is illegal and won't compile. _c has to be initialized before we get inside the braces
_b = B(NULL, 5, "hello"); // this is not illegal, but B might not have a default constructor or could have a very
// expensive construction that shouldn't be done more than once
}
to this version:
A::A( C& someC )
: _b(NULL, 5, "hello") // ok, initializing _b by passing these arguments to its constructor
, _c( someC ) // this reference to some instance of C is correctly initialized now
{}
Without using the initialiser list all class members will simply have their default constructor called so this is the only place that you can control which constructor is called (for non-dynamically allocated members). The same is true for which parent class constructor will be called.
Class members "initialised" within the body of the constructor (i.e. between the {} braces using the = operator) isn't technically initialisation, it's an assignment. For classes with a non-trivial constructor/destructor it can be costly to default construct and then modify through assignment in this way. For reference members you must use the initialiser list since they cannot be changed via the assignment operator.
If the member (or parent class) does not have a default constructor then failing to specify an appropriate constructor in the initialiser list will cause the compiler to generate an error. Otherwise the compiler will insert the default constructor calls itself. For built in types this does nothing so you will have garbage values there.
Note that the order in which you specify the members in the initialiser list does not affect the order in which they are called. It is always the parent class constructor (if any) first, then the class members in the order in which they are defined in the class definition. The order in which you put them in the initialiser list does not matter and can be the source of subtle bugs...
In the contrived example below it looks like the intention is to initialise m_b with value then m_a with m_b, but what actually happens is that m_a is initialised with m_b (which is itself not yet initialised) then m_b gets initialised with value. m_b will just contain garbage!
struct BadInitialiserListExample
{
BadInitialiserListExample(int value) :
m_b(value),
m_a(m_b) // <-- *BUG* this is actually executed first due to ordering below!
{
}
int m_a;
int m_b;
};