Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Uniform initialization syntax difference

What's the difference between doing

A a{ A() };

and,

A a( A{} );

to avoid the Most Vexing Parse? When should I use a particular one?

like image 524
Me myself and I Avatar asked May 31 '13 22:05

Me myself and I


People also ask

What is uniform initialization?

Uniform initialization is a feature in C++ 11 that allows the usage of a consistent syntax to initialize variables and objects ranging from primitive type to aggregates. In other words, it introduces brace-initialization that uses braces ({}) to enclose initializer values.

What is the point of uniform initialization in C++?

Uniform Initialization in C++ The uniform initialization is a feature that permits the usage of a consistent syntax to initialize variables and objects which are ranging from primitive type to aggregates. In other words, it introduces brace-initialization that applies braces ({}) to enclose initializer values.

What is the difference between initialization and assignment?

What is the difference between initialization and assignment? Initialization gives a variable an initial value at the point when it is created. Assignment gives a variable a value at some point after the variable is created.

What is uniform C++?

uniform, a C++ code which returns a sequence of uniformly distributed pseudorandom numbers. The fundamental underlying random number generator is based on a simple, old, and limited linear congruential random number generator originally used in the IBM System 360.


2 Answers

The two syntaxes are equivalent in most situations, and which one to choose is mostly a matter of taste. If you are into uniform initialization, I would suggest doing:

A a{ A{} };

Otherwise, parentheses alone can be used to disambiguate:

A a((A())); // This can't be parsed as a function declaration

Notice, that there is one situation (very unlikely, I must say) where the two forms shown in your question are not equivalent. If your class A has a constructor that takes an initializer_list<A>, that constructor will be favored over the copy constructor when the braces are used:

#include <initializer_list>
#include <iostream>

struct A
{
    A() { }
    A(std::initializer_list<A> l) { std::cout << "init-list" << std::endl; }
    A(A const& a) { std::cout << "copy-ctor" << std::endl; }
};

int main()
{
    A a(A{}); // Prints "copy-ctor" (or nothing, if copy elision is performed)
    A b{A()}; // Prints "init-list"
}

The above difference is shown in this live example.

like image 107
Andy Prowl Avatar answered Oct 30 '22 05:10

Andy Prowl


In most situations they are equivalent, but A a{ A() }; will prefer a std::initializer_list constructor if one is present, while A a( A{} ); will prefer a move/copy constructor.

When the construct ends up calling a move/copy constructor, the construction of the new object can be elided, but this is not possible for a std::initializer_list constructor.

Neither syntax will ever be parsed as a function declaration, so both avoid the most-vexing-parse.

#include <iostream>
#include <initializer_list>
struct A {
    A() {
        std::cout << "A()\n";
    }
    A(A&&) {
        std::cout << "A(A&&)\n";
    }
    A(std::initializer_list<A>) {
        std::cout << "A(std::initializer_list<A>)\n";
    }
};
int main()
{
    {A a{ A() };} // Prints "A()\n" "A(std::initializer_list<A>)\n"
    {A a( A{} );} // Prints "A()\n" and *possibly*
                  // (depending on copy elision) "A(A&&)\n"
}
like image 35
Mankarse Avatar answered Oct 30 '22 07:10

Mankarse