Benefits of Initialization lists - c++

Of what I know of benefits of using initialization list is that they provide efficiency when initializing class members which are not build-in. For example,
Fred::Fred() : x_(whatever) { }
is preferable to,
Fred::Fred() { x_ = whatever; }
if x is an object of a custom class. Other than that, this style is used even with built-in types for the sake of consistency.
The most common benefit of doing this is improved performance. If the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object.
With the other style, the expression whatever causes a separate, temporary object to be created, and this temporary object is passed into the x_ object's assignment operator. Then that temporary object is destructed at the ;. That's inefficient.
Question
Is there any efficiency gain in the following example with using initialization list.
I think there is no gain. The first version calls string's copy constructor and the other calls string's assignment operator (there isn't any temporary thats created). It that correct?
class MyClass
{
public:
MyClass(string n):name(n) { }
private:
string name;
};
class MyClass
{
public:
MyClass(string n)
{
name=n;
}
private:
string name;
};

The second version is calling string's default ctor and then string's copy-assignment operator -- there could definitely be (minor) efficiency losses compared to the first one, which directly calls c's copy-ctor (e.g., depending on string's implementation, there might be useless allocation-then-release of some tiny structure). Why not just always use the right way?-)

I think the only way to initialize const data members is in the initialization list
Eg. in the header:
class C
{
C();
private:
const int x;
int y;
}
And the in the cpp file:
C::C() :
x( 10 ),
y( 10 )
{
x = 20; // fails
y = 20;
}

It's a great way to initialize members that :
are const
don't have a default constructor (it's private)

Remember that there is a distinct difference between a copy constructor and an assignment operator:
the copy ctor constructs a new object using some other instance as a place to get initialization information from.
the assignment operator modifies an already existing object that has already been fully constructed (even if it's only by using a default constructor)
So in your second example, some work has already been done to create name by the time that
name=n;
is reached.
However, it's quite possible (especially in this simple example) that the work done is vanishingly small (probably just zeroing out some data members in the string object) and that the work is optimized away altogether in an optimized build. but it's still considered good form to use initializer lists whenever possible.

We can also perform the constructor delegation via the initialization list.

Related

Is there a way in C++ to deep copy only required variables in CCTOR? [duplicate]

I have a long class with a lot of data members. I want to write a copy constructor for it. But, if I write my own copy constructor, I lose access to the default copy constructor.
I just want to repair a few pointers in my own copy constructor. So I want to have a shallow copy of the object which can be done by the default copy constructor.
Is there a possibility to access the default copy constructor when I have my own copy constructor?
Wrap the things you don't want to change in a struct, and derive (privately) from it. In your copy constructor, simply invoke the copy constructor of your base class.
No you cannot have both default and your own copy c-tor.
But there are two workarounds with this problem:
1 Enclose your pointers in some class with defined copy semantics
Example:
class A {
public:
private:
int trivial1;
int trivial2;
...
SomePointer nontrivialMember;
};
class SomePointer {
public:
SomePointer(const SomePointer&); // here the non trivial part of A copy semantics
int* nonTrivialMember;
};
2 Enclose the trivial parameters in some trivial structure
Example:
class A {
public:
A(const A& o) : data(o.data) {
// non trivial part
}
private:
struct Data {
int trivial1;
int trivial2;
...
} data;
int* nontrivialMember;
};
I would always select the first solution.
[UPDATE]
There is also 3rd solution, very similar to my second, enclose your trivial part in privately inherited base class. I'd still prefer the 1st solution.
The simplest approach to this would be to wrap up the pointers into classes that will perform the 'repair' manually in their copy constructor, then you can happily use the default copy constructor.
No, there is no way to call the default copy constructor from an user defined copy constructor.
You can either use the default or your own, not both. If you want to choose different functionality for different objects you should just write a member function that handles that case.
void DeepCopy(MyClass* rhs);
For example.
You cannot access default copy ctor if you created your own - compiler just doesn't generate it. But ther is workaround - split you class into data structure and logic.
See example:
struct Data
{
int i;
std::string s;
Data(): i(), s() {}
};
class Code: private Data
{
public:
Code() {}
Code(const Code& rhs): Data(rhs) // Call default copy ctor
{
i = 42; // Your copy part
return *this;
}
};
My solution is a simple memcpy() instead of the impossible call to the implicit (compiler generated) copy constructor, as the example shown below:
Class Foo
{
public:
...
Foo (Foo & other) {
// copies trivial part (and non-trivial part with possible wrong values)
memcpy(this, &other, sizeof(Foo));
// your non-trivial part here, overwrites the wrong values (if any) above.
}
}
Yet the side-effect is that the memcpy() will also copy those non-trivial part, which is a waste. If the non-trivial part does not contain too much space, I will prefer my solution.
For example, a class like below wastes only 4 byte copy of the one pointer, assuming the size of a pointer is 4 bytes.
Class Bar
{
int x, y, z;
// memcpy() wastes these 4 bytes copy,
// since actual copy constructor wants a new string
string *s;
}
This worked for me... (C++11, don't know if it works on older std)
Not sure why it doesn't end up in an endless loop.
class Foo {
public:
Foo(const Foo &orig) {
*this = orig;
... exchange pointers, do own stuff
}

When are implicit move constructors not good enough?

When are implicit move constructors not good enough?
Should I treat it like destructors and copy constructors, where it's generally only necessary if I manage my own memory?
Is the implicit move constructor good enough in this (very contrived) scenario:
class A
{
private:
B b;
std::string name;
public:
A();
std::string getName() const {
return name;
}
B getB() const {
return b;
}
};
class B
{
private:
std::vector list;
public:
B();
std::vector getList() const {
return list;
}
};
The answer here is based on result of Google search.
Quoting from Andrzej's C++ blog
>
When should I define move constructor for my class?
It greatly depends on what your class does and how it is implemented. First, for ‘aggregate’ classes, which only group other data for convenience/clarity, move constructors will be implicitly generated by the compiler. Consider the following class.
struct Country {
std::string name;
std::vector<std::string> cities;
};
In a typical C++ struct many special member functions — like copy constructor, copy assignment, destructor — are auto-generated. This also includes move constructor (and move assignment).
For more sophisticated classes, which encapsulate their implementation details, the answer is more interesting. One of the main goals of move semantics (move constructor, move assignment) is to give the compiler two tools for implementing value semantics (passing arguments by value, returning by value) for user defined types:
Making two identical objects out of one — it needs to be expensive.
Moving one object from one memory location to the other — it can be
made very fast.
If for your class it is possible to implement move constructor that would be faster than the copy constructor, you should implement it for run-time speed optimization purposes. We have seen how it can be implemented for vector in this link. However, it is not for all types that such move constructor, faster than a copy constructor, can be implemented. Consider the following matrix representation.
class Matrix {
std::complex<long double> data[1000][1000];
};
Because all memory required for matrix representation is declared in class scope (unlike in vector, which uses heap-allocated memory) there is no way to apply only a small number of assignments. We will need to do a copying for each array element. There is no point in defining move constructor, as it will be no faster than copying.
Another valid reason for providing your move constructor if you want to enable your type that is non-copyable (because it is RAII-like and represents a resource) to be still passed by value where copying is not required, and stored in STL containers. Such unique ownership semantics are explained in more detail in this link.
Obligatory Rule of Zero answer: design either classes that manage a single resource - and thus override move/copy/destructor/assignment - or classes that aggregate resource managers and need no overrides.

Constructor initialization Vs assignment

Let us consider the following classes
class test1
{
private:
int a;
int b;
public:
test1():a(0),b(0){}
};
class test2
{
private:
int a;
int b;
public:
test2()
{
a=0;
b=0;
}
};
Now, I know that test1() constructor is the right way to initialize the data members of a class, because in test2() we are performing assignment and not initialization. My questions are:
What might go wrong if we perform assignment instead of initialization?
Doesn't the compiler internally perform assignment in case of test1() constructor? If not, then how are these initialized?
What might go wrong if we perform assignment instead of initialization?
Some class types (and also references and const objects) can't be assigned; some can't be default-initialised; some might be more expensive to default-initialise and reassign than to initialise directly.
Doesn't the compiler internally performs assignment in case of test1() constructor? If no then how are these initialized?
In the case of primitive types like int, there is little or no practical difference between the two. Default-initialisation does nothing, and direct-initialisation and assignment both do essentially the same thing.
In the case of class types, default-initialisation, assignment and direct-initialisation each call different user-defined functions, and some operations may not exist at all; so in general the two examples could have very different behaviour.
For your example there is no real different because you are initializing plain integers.
But assume these integers are objects with constructors, then the compiler would generate the following calls:
// test1
a::copy_constructor(0);
b::copy_constructor(0);
// test2
a::default_constructor();
b::default_constructor();
a::operator = (0);
b::operator = (0);
So depending on your objects test2 could have a huge performance impact. Also by initializing your objects in the initializing lists guaranties that your variables have the data when you enter the constructor. One 'drawback' of the initializer list is that the it is executed in the order that the variables are declared and not in the order of the initializer list, so it could be that you don't want to use the initializer list.
A third variant utilizing direct-list-initialization. Advantages are
variables don't have to be default-initialized in the constructor
the constructor and not the copy/move assignment operator is used to construct the members (as the other answers said, it doesn't matter for the primitive type of this example)
So this is less error-prone than both variants in the question:
#include <iostream>
class Test3
{
public: // Made public so we can easily output the vars. No struct is used to be consistent with question.
int a { 4 }; // No need for separate initialization in constructor.
int b { 2 }; // No need for separate initialization in constructor.
};
int main()
{
const auto t = std::move(Test3()); // Implicitly-declared default constructor + implicitly-declared move assignment operator
std::cout << t.a << t.b;
}
Output is 42.
Constructor-initializers allow initialization of data members at the time of their
creation.
Some programmers prefer to assign initial values in the body of the constructor. However, several data types must be initialized in a constructor-initializer. The following lines summarizes them:
const data members
You cannot legally assign a value to a const variable
after it is created. Any value must be supplied at the
time of creation.
Reference data members
References cannot exist without referring to
something.
Object data members for which there is no default constructor
C++ attempts to initialize member objects using a
default constructor. If no default constructor exists, it
cannot initialize the object.

C++ Collections Class

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

Initialisation and assignment

What EXACTLY is the difference between INITIALIZATION and ASSIGNMENT ?
PS : If possible please give examples in C and C++ , specifically .
Actually , I was confused by these statements ...
C++ provides another way of initializing member variables that allows us to initialize member variables when they are created rather than afterwards. This is done through use of an initialization list.
Using an initialization list is very similar to doing implicit assignments.
Oh my. Initialization and assignment. Well, that's confusion for sure!
To initialize is to make ready for use. And when we're talking about a variable, that means giving the variable a first, useful value. And one way to do that is by using an assignment.
So it's pretty subtle: assignment is one way to do initialization.
Assignment works well for initializing e.g. an int, but it doesn't work well for initializing e.g. a std::string. Why? Because the std::string object contains at least one pointer to dynamically allocated memory, and
if the object has not yet been initialized, that pointer needs to be set to point at a properly allocated buffer (block of memory to hold the string contents), but
if the object has already been initialized, then an assignment may have to deallocate the old buffer and allocate a new one.
So the std::string object's assignment operator evidently has to behave in two different ways, depending on whether the object has already been initialized or not!
Of course it doesn't behave in two different ways. Instead, for a std::string object the initialization is taken care of by a constructor. You can say that a constructor's job is to take the area of memory that will represent the object, and change the arbitrary bits there to something suitable for the object type, something that represents a valid object state.
That initialization from raw memory should ideally be done once for each object, before any other operations on the object.
And the C++ rules effectively guarantee that. At least as long as you don't use very low level facilities. One might call that the C++ construction guarantee.
So, this means that when you do
std::string s( "one" );
then you're doing simple construction from raw memory, but when you do
std::string s;
s = "two";
then you're first constructing s (with an object state representing an empty string), and then assigning to this already initialized s.
And that, finally, allows me to answer your question. From the point of view of language independent programming the first useful value is presumably the one that's assigned, and so in this view one thinks of the assignment as initialization. Yet, at the C++ technical level initialization has already been done, by a call of std::string's default constructor, so at this level one thinks of the declaration as initialization, and the assignment as just a later change of value.
So, especially the term "initialization" depends on the context!
Simply apply some common sense to sort out what Someone Else probably means.
Cheers & hth.,
In the simplest of terms:
int a = 0; // initialization of a to 0
a = 1; // assignment of a to 1
For built in types its relatively straight forward. For user defined types it can get more complex. Have a look at this article.
For instance:
class A
{
public:
A() : val_(0) // initializer list, initializes val_
{}
A(const int v) : val_(v) // initializes val_
{}
A(const A& rhs) : val_(rhs.val_) // still initialization of val_
{}
private:
int val_;
};
// all initialization:
A a;
A a2(4);
A a3(a2);
a = a3; // assignment
Initialization is creating an instance(of type) with certain value.
int i = 0;
Assignment is to give value to an already created instance(of type).
int i;
i = 0
To Answer your edited Question:
What is the difference between Initializing And Assignment inside constructor? &
What is the advantage?
There is a difference between Initializing a member using initializer list and assigning it an value inside the constructor body.
When you initialize fields via initializer list the constructors will be called once.
If you use the assignment then the fields will be first initialized with default constructors and then reassigned (via assignment operator) with actual values.
As you see there is an additional overhead of creation & assignment in the latter, which might be considerable for user defined classes.
For an integer data type or POD class members there is no practical overhead.
An Code Example:
class Myclass
{
public:
Myclass (unsigned int param) : param_ (param)
{
}
unsigned int param () const
{
return param_;
}
private:
unsigned int param_;
};
In the above example:
Myclass (unsigned int param) : param_ (param)
This construct is called a Member Initializer List in C++.
It initializes a member param_ to a value param.
When do you HAVE TO use member Initializer list?
You will have(rather forced) to use a Member Initializer list if:
Your class has a reference member
Your class has a const member or
Your class doesn't have a default constructor
Initialisation: giving an object an initial value:
int a(0);
int b = 2;
int c = a;
int d(c);
std::vector<int> e;
Assignment: assigning a new value to an object:
a = b;
b = 5;
c = a;
d = 2;
In C the general syntax for initialization is with {}:
struct toto { unsigned a; double c[2] };
struct toto T = { 3, { 4.5, 3.1 } };
struct toto S = { .c = { [1] = 7.0 }, .a = 32 };
The one for S is called "designated initializers" and is only available from C99 onward.
Fields that are omitted are automatically initialized with the
correct 0 for the corresponding type.
this syntax applies even to basic data types like double r = { 1.0
};
There is a catchall initializer that sets all fields to 0, namely { 0 }.
if the variable is of static linkage all expressions of the
initializer must be constant expressions
This {} syntax can not be used directly for assignment, but in C99 you can use compound literals instead like
S = (struct toto){ .c = { [1] = 5.0 } };
So by first creating a temporary object on the RHS and assigning this to your object.
One thing that nobody has yet mentioned is the difference between initialisation and assignment of class fields in the constructor.
Let us consider the class:
class Thing
{
int num;
char c;
public:
Thing();
};
Thing::Thing()
: num(5)
{
c = 'a';
}
What we have here is a constructor that initialises Thing::num to the value of 5, and assigns 'a' to Thing::c. In this case the difference is minor, but as was said before if you were to substitute int and char in this example for some arbitrary classes, we would be talking about the difference between calling a parameterised constructor versus a default constructor followed by operator= function.