Parashift explains initialization lists well, but does not explain why an extra copy of a variable is created before assignment in the ctor body, but no extra copy is created when assigned through an initialization list.
I've even come across advice of using ++i instead of i++ because the former avoids creation of a temporary i before assignment. Is it the same for POD's assigned in a ctor body? A temp variable gets created before the assignment happens?
To put it another way, why does the compiler need to create an extra copy of a variable? Why can't it just assign the variable directly?
Why?
Direct Initialization or Assignment Operator (Syntax) This assigns the value of one object to another object both of which are already exists. Copy initialization is used when a new object is created with some existing object. This is used when we want to assign existing object to new object.
Initialization is the process of locating and using the defined values for variable data that is used by a computer program. For example, an operating system or application program is installed with default or user-specified values that determine certain aspects of how the system or program is to function.
Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.
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.
Consider the following:
struct C {
C() { /* construct the object */ }
};
struct X {
C member;
X() { member = C(); }
};
The X()
constructor is the same as if you had said:
X() : member() { member = C(); }
First, the C
constructor is called to construct the member
data member. Then the body of X
is executed, a second, temporary C
object is created and assigned to member
, then the temporary is destroyed.
Note that this is only the case for types that are initialized automatically. If member
was of type int
or of a POD class type (as examples), it would be uninitalized when the body of the X
constructor is entered.
For such types it doesn't really matter from a performance standpoint whether you initialize the data member in the initialization list or assign to the data member in the body of the constructor; the difference is entirely stylistic. Where possible, the initialization list should still be preferred for the sake of consistency.
To address your first question specifically regarding the copy (without touching on "++i" vs "i++"):
The constructor is a function, and it has parameters. These parameters are copies of the variables passed as parameters (unless passing by reference is used). You can now manipulate this copy or do anything else with it. Then when you assign, you take this copy of the parameter (possibility manipulated) and assign it to the member variable. When you use an initialization list, the compiler can optimize the assignment immediately without this copy, as you will not be using it for anything but the initialization (and cannot modify it before assigning it to the member variable).
why an extra copy of a variable is created before assignment in the ctor body, but no extra copy is created when assigned through an initialization list.
Because assignment follows initialization. In other words, assignment is optional, but initialization is mandatory. You may not notice much difference for PODs. But the same holds true for user defined data types.
advice of using ++i instead of i++
Again for PODs it doesn't matter much. But for user defined classes, i++
does create a temporary copy. So it's better to use ++i
.
struct A {
A operator ++ (int) // example of i++
{
A temp = *this;
this->value ++;
return temp; // makes 2 copies "temp" and return value
}
A& operator ++ () // example of ++i
{
this->value ++;
return *this; // no copy
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With