统一初始化语法差异

Me *_*d I 10 c++ most-vexing-parse c++11

这样做有什么区别

A a{ A() };
Run Code Online (Sandbox Code Playgroud)

和,

A a( A{} );
Run Code Online (Sandbox Code Playgroud)

避免最烦恼的解析?我什么时候应该使用特定的?

And*_*owl 13

在大多数情况下,这两种语法是等价的,选择哪一种主要是品味问题.如果你进入统一初始化,我建议做:

A a{ A{} };
Run Code Online (Sandbox Code Playgroud)

否则,可以单独使用括号来消除歧义:

A a((A())); // This can't be parsed as a function declaration
Run Code Online (Sandbox Code Playgroud)

请注意,有一种情况(我不得不说),你问题中显示的两种形式并不等同.如果你的类A有一个构造函数,initializer_list<A>当使用大括号时,该构造函数将优先于复制构造函数:

#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"
}
Run Code Online (Sandbox Code Playgroud)

上面的差异显示在这个实例中.

  • 实际上,第一个*不会*为我打印"copy-ctor".我认为它的副本省略. (2认同)
  • 请注意,"-fno-elide-constructors"在clang上[目前已被破坏](http://llvm.org/bugs/show_bug.cgi?id=12208). (2认同)

Man*_*rse 9

在大多数情况下,它们是等价的,但如果存在构造函数,A a{ A() };则更喜欢std::initializer_list构造函数,而A a( A{} );更喜欢移动/复制构造函数.

当构造最终调用移动/复制构造函数时,可以省略新对象的构造,但这对于std::initializer_list构造函数是不可能的.

这两种语法都不会被解析为函数声明,所以两者都避免了最令人烦恼的解析.

#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"
}
Run Code Online (Sandbox Code Playgroud)