c++初始化列表和默认值

C++ initializer list and default values

本文关键字:默认值 列表 初始化 c++      更新时间:2023-10-16

这段代码在c++ 14中有效吗

using namespace std;
struct Point
{
  int x = 0;
  int y = 0;
};
Point p2 {1, 1};

它在clang++ 7.0中可以很好地编译,但在g++ 4.9中不能工作,在这两种情况下,我将——std=c++1y传递给编译器。

在g++中,当我从struct定义中删除默认值时,它会工作。

g++ test_constexpr_ctor.cc --std=c++1y -o test
test_constexpr_ctor.cc:7:15: error: no matching function for call to ‘Point::Point(<brace-enclosed initializer list>)’
Point p2 {1, 1};
            ^
test_constexpr_ctor.cc:7:15: note: candidates are:
test_constexpr_ctor.cc:1:8: note: constexpr Point::Point()
struct Point
        ^
test_constexpr_ctor.cc:1:8: note:   candidate expects 0 arguments, 2 provided
test_constexpr_ctor.cc:1:8: note: constexpr Point::Point(const Point&)
test_constexpr_ctor.cc:1:8: note:   candidate expects 1 argument, 2 provided
test_constexpr_ctor.cc:1:8: note: constexpr Point::Point(Point&&)
test_constexpr_ctor.cc:1:8: note:   candidate expects 1 argument, 2 provided

代码有效。

  1. (8.5.4/3):
类型的对象或引用的列表初始化T定义如下:—如果T是聚合,则执行聚合初始化
  • c++14中的聚合定义为(8.5.1/1):
  • 一个总是一个数组还是一个类(子句9),没有用户提供的构造函数(12.1),没有私人或受保护的非静态数据成员11),没有基类(子句10),而没有虚函数(10.3) .

    注意,在c++11中,这个定义看起来不同(强调我的):

    一个总是一个数组还是一个类(子句9),没有用户提供的构造函数(12.1), brace-or-equal -初始化器S表示非静态数据成员(9.2),没有私有或受保护的非静态数据成员11),无基类(子句)10),而没有虚函数(10.3) .

    因为这部分在c++14中被删除了,所以你的结构肯定是一个聚合,因此应该执行聚合初始化。

    这在gcc5中是固定的(在变更列表中搜索"具有非静态数据成员初始化器的聚合")。我不认为这是一个"bug",而是gcc团队只在gcc 5.1.0中实现了这个变化。

    你贴的代码是绝对正确的。

    然而,你的行为是一个尚未关闭的g++ 4.9.1版本的错误。实际上,它可能是一个副本,并在其他一些错误报告中关闭,因为这个问题在g++ 5.1.0或更早的版本中已经修复。要查找实际的bug,可以使用bugzilla的搜索。