逐字段构造函数生成的规则是什么?
What are the rules of field-by-field constructor generation?
我发现类使用初始化列表语法的可能性取决于类字段是否具有默认值。为什么?
更准确地说,考虑下面的代码:
class S
{
public:
int a;
};
...
int a;
S s{ a };
编译时没有任何问题。但是如果我给class字段添加一个默认值,它就会停止构建:
class S
{
public:
int a = 0;
};
...
int a;
S s{ a };
错误1错误C2440: 'initializing':无法从'initializer-list'转换为'S'
为什么?还有什么影响构造函数的生成?
在 c++ 14中,你的代码是有效的,可以用任何c++ 14兼容的编译器编译。
c++ 11然而:
如果您没有a
的默认值,则您的类型是聚合,因此可以执行聚合初始化:
聚合是下列类型之一:
数据类型
类类型(通常是struct或union),具有
- 没有私有或受保护的非静态数据成员
- 没有用户提供的构造函数,包括从公共基继承的构造函数(自c++ 17起)(允许显式默认或删除构造函数)(自c++ 11起)
- 没有虚的、私有的或受保护的(c++ 17起)基类
- 没有虚成员函数
- 没有默认的成员初始化式(从c++ 11开始,直到c++ 14)
一旦您为属性a
添加了默认值,您的聚合初始化就不能再执行了,因为您的类型不再是聚合。
显示的代码在编译gcc 6.1.1时没有任何问题。您可能使用的是不完全支持c++ 14的旧编译器:
$ cat t.C
class S
{
public:
int a = 0;
};
void foo()
{
int a=4;
S s{a};
}
$ g++ -std=c++1z -g -c -o t.o t.C
$ g++ --version
g++ (GCC) 6.1.1 20160510 (Red Hat 6.1.1-2)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
在这两种情况下,S
的默认构造函数都不接受参数。类的形式不会影响默认构造函数的生成。此外,没有采用int
的隐式生成的构造函数。
如果S
是聚合,则使用S s = { arguments_opt };
不会调用S
的构造函数。相反,它调用名为聚合初始化的东西。聚合类是唯一可以在不调用构造函数的情况下创建该类对象的类。
只有当S
是而不是聚合时,S s = { arguments_opt };
才尝试将实参列表与S
的构造函数的形参进行匹配。
(正如其他人所解释的,在c++ 11中,为非静态数据成员提供大括号或等号初始化式使类不是聚合)。
相关文章:
- 为什么此指针值不能转换为整数的规则是什么?
- 假设声明中某些上下文中需要的名称查找规则是什么
- 在 C++20 中对概念约束函数进行排序的规则是什么?
- 自动参数捕获的扣除规则是什么?
- c++ 17 中结构自动定义构造函数的规则是什么?
- 在 Objective-C++ 中应用于__weak指针时,通过关键字推导类型"auto"规则是什么?
- 在平等符号左侧使用RVALUE参考的规则是什么?
- 类静态变量初始化的规则是什么?
- 初始化中的模板转换运算符类型推导规则是什么?
- 将临时值存储为某种数据类型时,算术运算的标准规则是什么
- 使用“void”来专门化模板的规则是什么?
- 对于C++,在另一个函数中定义一个函数的可行性规则是什么?
- 有人能解释一下最多一次不变和存在、所有权和守恒规则是什么吗?
- 标准函数的函数指针和成员函数指针的规则是什么
- 在C++11类型推理过程中,控制优先级的规则是什么
- 从char数组中强制转换*时,严格的别名规则是什么
- 对于 C++ lambda,通过引用捕获引用的规则是什么
- decltype(右值表达式)的类型推导规则是什么
- 对于默认定义的移动构造函数,noexcept的规则是什么
- 在好友声明中使用限定名称的规则是什么?