【问题标题】:Constructor, initializer list and different behaviour in g++ and clangg++ 和 clang 中的构造函数、初始化列表和不同的行为
【发布时间】:2016-04-13 10:03:43
【问题描述】:

这是简化的代码:

#include <vector>

class VInitList
{
public:
    explicit VInitList(std::vector<int> v){}
};

int main()
{
    VInitList vil({{}});
}

并用 g++ 5.2.1 编译得到这个错误:

 error: call of overloaded ‘VInitList(<brace-enclosed initializer list>)’ is ambiguous
     VInitList vil({{}});
                       ^
main.cpp:6:5: note: candidate: VInitList::VInitList(std::vector<int>)
     VInitList(std::vector<int> v){}
     ^
main.cpp:3:7: note: candidate: constexpr VInitList::VInitList(const VInitList&)
     class VInitList
           ^
main.cpp:3:7: note: candidate: constexpr VInitList::VInitList(VInitList&&)

当我看到编译器错误时,我发现我写错了{{}}(是的,不要对我卑鄙),但我仍然无法理解错误。恕我直言,编译器必须摆脱额外的 {} 或返回语法错误。

然后我尝试编译这个:

std::vector<int> v = {{{}}};

按预期工作。

【问题讨论】:

  • 我只浏览了您的示例,但您在编译的代码 sn-p 上多了一对括号,也许这就是原因?
  • 它不能在 g++ 5.2.1 中编译,但在 Clang 3.7.0 中可以编译
  • 有趣的问题。在您的场景中,单个{} 似乎在这两种情况下都足够了。包含的类型是int,为什么要复杂化? :-)

标签: c++ c++11 vector g++ initializer-list


【解决方案1】:

但是std::vector&lt;int&gt; v = {{{}}}; 并没有按照你的想法去做;它用一个int 元素初始化一个向量,初始化为零。这是因为int 可以被列表初始化:

int i{};   // assert(i == 0)

所以std::vector&lt;int&gt; v = {{{}}};被解析为:

std::vector<int> v = {{{}}};
                       ^-- int
                      ^-- initializer_list<int>
                     ^-- vector<int>

同样,如果你写

VInitList vil{{{}}};
               ^-- int
              ^-- vector<int>
             ^-- VInitList 

包含的vector&lt;int&gt; 有 1 个元素,初始化为零。 (initializer_list&lt;int&gt; 阶段可以省略,因为vector(initializer_list&lt;int&gt;) 构造函数不是explicit)。

所以VInitList vil({{}}); 可以解析为:

VInitList vil({{}});
               ^-- int
              ^-- vector<int>

或作为

VInitList vil({{}});
               ^-- vector<int>
              ^-- VInitList

在第一种情况下,vector 有 1 个元素;在第二种情况下,它是空的。 gcc 拒绝您的代码也一样。

Clang 只将其解析为前者;我不确定哪个是正确的。

【讨论】:

  • 很有趣,我不知道 int 可以被列表初始化。为什么会这样?为什么?
  • @FrankS101 一致性,主要是 - 这意味着您可以在任何希望将对象初始化为“空”状态的地方使用{}= {}。请注意,在 C++98 中,您可以在不会与函数声明混淆的地方使用 (),例如成员初始化器:struct S { int i; S() : i() {} };
猜你喜欢
  • 2018-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-25
  • 1970-01-01
  • 2013-10-03
  • 1970-01-01
相关资源
最近更新 更多