Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different ways of calling an initializer-list-constructor

Consider this example for initializer-list-constructor usage:

std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" };
std::vector<std::string> v({ "xyzzy", "plugh", "abracadabra" });
std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" }; 

Are there any differences (even slightly) between them?

In a large project, where you have to define a standard, which style would you choose?
I would prefer the first style, the third can be easly confused with a call to a constructor with args. Also the first style looks familiar to other programming languages.

like image 766
dynamic Avatar asked Aug 04 '14 14:08

dynamic


People also ask

What are the different ways of calling constructor?

There are two types of constructors in Java: Default constructor (no-arg constructor) Parameterized constructor.

Does initializer list call constructor?

An initialization list can be used to explicitly call a constructor that takes arguments for a data member that is an object of another class (see the employee constructor example above). In a derived class constructor, an initialization list can be used to explicitly call a base class constructor that takes arguments.

What is a constructor initializer list?

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.

Does initializer list run before constructor?

The initializer list is used to directly initialize data members of a class. An initializer list starts after the constructor name and its parameters.


Video Answer


1 Answers

In case of a vector of strings, there's no difference between the three forms. There can, however, be a difference between the first and the other two if the constructor taking the initializer_list is explicit. In that case, the first, which is copy-list-initialization, is not allowed, while the other two, which are direct-list-initialization, are allowed.

Because of that reason, my preference would be the third form. I'd avoid the second because the parentheses are redundant.


Further differences arise, as Yakk points out in the comments, when the type being constructed does not have a constructor taking an initializer_list.

Say for instance, the type being constructed has a constructor that takes 3 arguments, all of type char const *, instead of the initializer_list constructor. In that case, forms 1 & 3 are valid, but 2 is ill-formed, because the braced-init-list cannot match the 3 argument constructor when enclosed in parentheses.

If the type does have an initializer list constructor, but the elements of the braced-init-list are not implicitly convertible to initializer_list<T>, then other constructors will be considered. Assuming another constructor that is a match exists, form 2 results in an intermediate copy being constructed, while the other two don't. This can be demonstrated by the following example, compiled with -fno-elide-constructors.

struct foo
{
    foo(int, int) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    foo(foo const&) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
    foo(std::initializer_list<std::string>) { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

int main()
{
    foo f1 = {1,2};
    std::cout << "----\n";
    foo f2({1,2});
    std::cout << "----\n";
    foo f3{1,2};
}

Output:

foo::foo(int, int)
----
foo::foo(int, int)
foo::foo(const foo&)
----
foo::foo(int, int)


The following case is not part of the question, but still good to be aware of. Using nested braces can result in unintuitive behavior in certain cases. Consider

std::vector<std::string> v1{{ "xyzzy", "plugh", "abracadabra" }};
std::vector<std::string> v2{{ "xyzzy", "plugh"}};

v1 works as expected and will be a vector containing 3 strings, while v2 results in undefined behavior. Refer to this answer for a detailed explanation.

like image 89
Praetorian Avatar answered Sep 22 '22 10:09

Praetorian