【问题标题】:Uniform initialization syntax difference统一初始化语法差异
【发布时间】:2013-05-31 22:41:21
【问题描述】:

做和做有什么区别

A a{ A() };

和,

A a( A{} );

避免Most Vexing Parse?我应该什么时候使用特定的?

【问题讨论】:

  • 在这种特殊情况下,最简单的选择是A a;,对吧?如果我没有误解这一点,那么您建议的语法只有在您要传递给A 的构造函数的临时值与A 的类型不同时才有意义,对吗? IE。 A a { B() };.

标签: c++ c++11 most-vexing-parse


【解决方案1】:

这两种语法在大多数情况下是等价的,选择哪一种主要是个人喜好问题。如果您要进行统一初始化,我建议您这样做:

A a{ A{} };

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

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

请注意,有一种情况(我必须说非常不可能)您的问题中显示的两种形式不等价。如果您的类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"
}

上面的区别体现在这个live example中。

【讨论】:

  • 实际上,第一个没有为我打印“copy-ctor”。我认为它的复制省略。
  • @MemyselfandI:嗯,是的,编译器正在忽略复制 - 但从概念上讲,选择了复制构造函数
  • 复制省略是否仅在启用优化时发生?
  • @MemyselfandI:不。在许多编译器上,除非您特别禁用它,否则它将始终启用。
  • 请注意 -fno-elide-constructors 在 clang 上是 currently broken
【解决方案2】:

在大多数情况下,它们是等价的,但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"
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-03
    • 2023-01-10
    • 1970-01-01
    • 2020-03-18
    • 1970-01-01
    • 2022-01-09
    相关资源
    最近更新 更多