It was suggested by a team member that using an intializer like this:
return Demo{ *this };
was better than:
return Demo(*this);
Assuming a simple class like this:
class Demo {
public:
int value1;
Demo(){}
Demo(Demo& demo) {
this->value1 = demo.value1;
}
Demo Clone() {
return Demo{ *this };
}
};
I admit to having not seen the { *this }
syntax before, and couldn't find a reference that explained it well enough that I understood how the two options differed. Is there a performance benefit, a syntax choice, or something more?
There are two ways to initialize a class object: Using a parenthesized expression list. The compiler calls the constructor of the class using this list as the constructor's argument list. Using a single initialization value and the = operator.
The __init__ function is called every time an object is created from a class. The __init__ method lets the class initialize the object's attributes and serves no other purpose. It is only used within classes.
__init__ method "__init__" is a reseved method in python classes. It is called as a constructor in object oriented terminology. This method is called when an object is created from a class and it allows the class to initialize the attributes of the class.
Your colleague is missing a trick with "uniform initialization", there is no need for the type-name when it is known. E.g. when creating a return value. Clone
could be defined as:
Demo Clone() {
return {*this};
}
This will call the Demo
copy constructor as needed. Whether you think this is better or not, is up to you.
In GOTW 1 Sutter states as a guideline:
Guideline: Prefer to use initialization with { }, such as vector v = { 1, 2, 3, 4 }; or auto v = vector{ 1, 2, 3, 4 };, because it’s more consistent, more correct, and avoids having to know about old-style pitfalls at all. In single-argument cases where you prefer to see only the = sign, such as int i = 42; and auto x = anything; omitting the braces is fine. …
In particular, using braces can avoid confusion with:
Demo d(); //function declaration, but looks like it might construct a Demo
Demo d{}; //constructs a Demo, as you'd expect
The brace syntax will use a constructor that takes an initializer list first, if one exists. Otherwise it will use a normal constructor. It also prevents the chance of the vexing parse listed above.
There is also different behaviour when using copy initialization. With the standard way
Demo d = x;
The compiler has the option to convert x
to a Demo
if necessary and then move/copy the converted r-value into w
. Something similar to Demo d(Demo(x));
meaning that more than one constructor is called.
Demo d = {x};
This is equivalent to Demo d{x}
and guarantees that only one constructor will be called. With both assignments above explicit constructors are cannot be used.
As mentioned in the comments, there are some pitfalls. With classes that take an initializer_list
and have "normal" constructors can cause confusion.
vector<int> v{5}; // vector containing one element of '5'
vector<int> v(5); // vector containing five elements.
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