18

考虑以下示例:

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

在为 id clang 3.x 和 gcc 4.8.x 定义没有默认值的结构 ABC 时,编译代码没有问题。但是,在为“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 时会发生什么,为什么在这种情况下无法进行聚合初始化?我是否隐含地定义了某种构造函数?

4

2 回答 2

33

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};初始化 astruct ABC.因为它不再保持聚合类型。但是您的代码在 C++14 中有效。(在此处查看现场演示)。

于 2016-03-09T12:44:40.560 回答
-1

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

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;
}
于 2016-03-09T12:34:42.570 回答