使用聚合初始化和成员初始值设定项初始化结构

use*_*r16 16 c++ constructor aggregate-initialization c++11

请考虑以下示例:

#include <iostream>
#include <string>
struct ABC
{
    std::string str;
    unsigned int id ;/* = 0 : error: no matching constructor for initialization of 'ABC'*/
};

int main()
{
    ABC abc{"hi", 0};
    std::cout << abc.str << " " << abc.id <<   std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在定义结构ABC而没有id clang 3.x和gcc 4.8.x的默认值时,编译代码没有问题.但是,在为"id"添加默认参数后,我得到了流动的错误消息:

13 : error: no matching constructor for initialization of 'ABC'
ABC abc{"hi", 0};
^ ~~~~~~~~~
4 : note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
struct ABC
^
4 : note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
4 : note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 2 were provided
1 error generated.
Compilation failed
Run Code Online (Sandbox Code Playgroud)

从技术角度来看,当我使用默认参数定义id时会发生什么,为什么在这种情况下聚合初始化不可能?我是否隐式定义了某种构造函数?

Des*_*tor 29

Bjarne Stroustrup和Richard Smith提出了一个关于聚合初始化和成员初始化器无法协同工作的问题.

在C++ 11和C++ 14标准中,聚合的定义略有改变.

从C++ 11标准草案n3337第8.5.1节说:

聚合是一个数组或类(第9节),没有用户提供的构造函数(12.1),非静态数据成员(9.2)没有大括号或相等的初始值,没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3).

但是C++ 14标准草案n3797第8.5.1节说:

聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第11条),没有基类(第10条),没有虚函数(10.3) ).

因此,当您在C++ 11中为数据成员使用类成员初始化程序(即相等的初始化程序)时,id它不再保持聚合而您无法编写ABC abc{"hi", 0};以初始化a struct ABC.因为它之后不再是聚合类型.但是你的代码在C++ 14中是有效的.(见此处的现场演示).

  • 标准之间的优秀比较.+1 (5认同)