【问题标题】:Visual C++ initialization inconsistence with gcc and clangVisual C++ 初始化与 gcc 和 clang 不一致
【发布时间】:2016-12-10 06:30:09
【问题描述】:

下面这段代码prints 0 compiled with vc++prints 1 compiled with g++ or clang++

#include <iostream>
#include <vector>

struct S
{
    S() = default;

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

int main()
{
    std::vector<S> s{{}};

    std::cout << s.front().v.size() << std::endl;
}

这是 vc++ 中的错误吗?

如果提供了用户定义的构造函数(S() {}; 而不是S() = default;vc++ starts to print 1, too

【问题讨论】:

  • 看起来确实像 vc++ 编译器中的编译器错误。
  • 我似乎记得 C++17 中即将发生变化,即大括号初始化程序只有一个项目。如果将 0 更改为 13 会发生什么?
  • @Cheersandhth.-Alf 例如std::vector&lt;int&gt; v{ 11,22 }; 产生同样的问题。

标签: c++ visual-c++ initialization c++14 list-initialization


【解决方案1】:

在阅读标准 (C++11 n3485) 时,12.6.2/9 声明:

如果给定的非静态数据成员同时具有brace-or-equal-initializermem-initializer,则执行mem-initializer 指定的初始化,并忽略非静态数据成员的brace-or-equal-initializer

所以问题变成了default,即隐式定义的构造函数是否包含mem-initializer

12.1/6 部分指出:

隐式定义的默认构造函数执行类的一组初始化,这些初始化将由用户编写的该类的默认构造函数执行,没有ctor-initializer (12.6.2) 和空的compound-statement

这意味着隐式生成的(默认)构造函数没有mem-initializers,并且确实应该使用类内初始化程序(上面引用中的brace-or-equal-initializer)。

MSVC 在这里错了(这并不奇怪,真的)。

【讨论】:

    【解决方案2】:

    这不是答案,而是需要代码的注释。

    我认为下面更清楚地说明了编译器的差异:

    #include <iostream>
    #include <vector>
    
    struct S
    {
        S() = default;
    
        std::vector<int> v = std::vector<int>(13);
    };
    
    int main()
    {
        std::vector<S> s{{}};
        std::cout << s.front().v.size() << std::endl;
    }
    

    这里 g++ MinGW 5.1.0 报告 13 个项目,而 MSVC 2015 更新 2 报告 0 个项目。

    即g++ 使用类中指定的初始化程序,而 MSVC 使用s 声明中指定的初始化程序。对我来说,这看起来像是 g++ 的问题。但我不确定:唯一可以确定的是两者都不对。

    【讨论】:

      猜你喜欢
      • 2014-04-11
      • 1970-01-01
      • 2018-11-29
      • 2015-09-26
      • 2017-02-27
      • 1970-01-01
      • 2021-05-15
      • 2019-12-20
      • 1970-01-01
      相关资源
      最近更新 更多