使用聚合初始化和成员初始化器初始化结构

Initializing a struct with aggregate initialization and member initializers

考虑以下示例:

#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;
}

定义结构 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

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

在 c++ 中,struct 和 类 是相同的,只是结构有默认的 public 成员,而 类 有私有成员。如果你想使用初始值我认为你必须编写一个构造函数或使用这样的东西:

struct ABC
{
    std::string str;
    unsigned int id;
} ABC_default = {"init", 0 }; //initial values

int main()
{
    ABC abc = ABC_default;
    std::cout << abc.str << " " << abc.id << std::endl;
    return 0;
}

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

聚合的定义在 C++11 和 C++14 标准中略有变化。

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

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal- initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

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

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

因此,当您在 class 中为数据成员 id 在 C++11 中它不再保持聚合类型并且你不能写 ABC abc{"hi", 0}; 来初始化一个 struct ABC. 因为在那之后它不再保持聚合类型。但是你的代码在 C++14 中是有效的。 (查看现场演示 here)。