本周小贴士#172:指定初始化器

作为TotW#171最初发表于2019年12月11日

由Aaron Jacobs创作

指定初始化器是 C++20 标准草案中的一种语法,用于以紧凑但易读且易维护的方式指定结构体的内容。它可以替代重复性的代码,例如:

struct Point {
double x;
double y;
double z;
};

Point point;
point.x = 3.0;
point.y = 4.0;
point.z = 5.0;

使用指定初始化器可以更简洁地书写:

Point point = {
.x = 3.0,
.y = 4.0,
.z = 5.0,
};

除了语法更简洁之外,指定初始化器可在更多的上下文中使用。例如,它意味着可以将结构体设置为 const 而无需采用笨拙的解决方案:

// 明确告诉读者(大段代码的潜在复杂),这个结构体永远不会改变。
const Point character_position = {.x = 3.0};

或可以直接在函数调用中使用而不引入额外的标识符到作用域中:

std::vector<Point> points;

[...]

points.push_back(Point{.x = 3.0, .y = 3.0});
points.push_back(Point{.x = 4.0, .y = 4.0});

语义

指定初始化器是聚合初始化的一种形式,因此只能用于聚合。这意味着“没有用户提供的构造函数或虚函数的结构体或类”,这在 Google 风格中使用 struct 时大致如此。

C++20 指定初始化器的语义与 C++ 的其他语言特性(如构造函数中的成员初始化列表)相似。显式命名的字段按提供的表达式顺序进行初始化,可以省略需要具有“默认”行为的字段:

Point point = {
.x = 1.0,
// y 将为 0.0
.z = 2.0,
};

上面的“默认”意味着什么?除了联合等特殊情况外,答案是:

  • 如果结构体定义包含默认成员初始化器(即字段定义看起来像 std::string foo = “default value”😉,则使用该初始化器。
  • 否则,该字段将被初始化为 = {}。在实践中,这意味着对于纯粹的旧数据类型,您将获得零值,而对于更复杂的类,您将获得一个默认构造的实例。
    这通常是最少惊讶的行为。详细信息请参见标准。

一些历史和语言趣闻

指定初始化器自 C99 以来一直是 C 语言的标准部分,并且在此之前已被编译器提供为非标准扩展。但是,直到最近,它们还不是 C++ 的一部分:这是 C 不是 C++ 的一个著名例子。因此,Google 风格指南曾经说不要使用它们。

经过二十年后,情况终于发生了变化:指定初始化器现在已成为 C++20 标准的一部分。

与 C 版本相比,C++20 版本的指定初始化器有一些限制:

  • C++20要求在指示符中列出的字段顺序必须与结构体定义中列出的顺序相同(因此 Point{.y = 1.0, .x = 2.0} 是不合法的)。而 C 不需要这样做。

  • C允许您混合使用指定的和非指定的初始化器(Point{1.0, .z = 2.0}),但是 C++20 不允许这样做。

  • C支持稀疏初始化数组的语法,称为“数组指示符”,但这不是 C++20 的一部分。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值