对于熟悉 c99 的人来说,Designated Initializers 并不算是什么新鲜事物,然而 c++直到 c++20 才正式支持这一特性。 虽然在 c++20 之前,像 GCC 这样的编译器通过扩展的形式已经对该特性做了支持,但是随着 c++20 将其纳入新标准,这一特性将在所有编译器中得到支持。
基本用法
Designated Initialization 是聚合初始化(Aggregate Initialization)的一种形式。 在 c++20 中,聚合类型(Aggregate types)是指:
- 数组类型
- 具备如下特性的 class 类型:
- has no private or protected direct non-static data members
- has no user-declared or inherited constructors
- has no virtual, private, or protected base classes
- has no virtual member functions
c++20 中的 Designated Initializers 的用法跟 c99 非常相似:
1struct Points
2{
3 double x{0.0};
4 double y{0.0};
5};
6
7const Points p{.x = 1.1, .y = 2.2};
8const Points o{.x{1.1}, .y{2.2}};
9const Points x{.x = 1.1, .y{2.2}};
优点
使用 Designated Initializers 最大的好处就是能够提升代码的可读性。
我们考拿下面的例子来说,首先声明一个struct Date
,其中有三个int
类型的成员变量,分别代表了年、月、日。
如果没有 Designated Initializers,我们对它进行初始化通常会这样做:
1Date someday {2022, 3, 15};
而使用 Designated Initializers:
1Date someday { .year = 2022, .mon = 3, .day = 15 };
很显然,使用 Designated Initializers 能让人一目了然,知道每个数字的含义,而不使用的话,必须要回过头去看Date
结构的定义才能确定这几个数字代表啥意思。
使用规则
c++20 中的 Designated Initializers 遵循一下规则:
- 只能用于聚合类型初始化(aggregate initialization)
- Designators 只能是非静态类型的成员
- Designators 的顺序应该跟成员声明时的顺序保持一致
- 并不是所有成员都要指定,可以跳过一些成员
- 普通的初始化和 Designated Initializers 不能混用
- Designators 不支持嵌套,例如
.x.y = 10
是不允许的
下面是一些代码示例:
1#include <iostream>
2#include <string>
3
4struct Product
5{
6 std::string name_;
7 bool inStock_{false};
8 double price_ = 0.0;
9};
10
11void Print(const Product& p)
12{
13 std::cout << "name: " << p.name_ << ", in stock: " << std::boolalpha << p.inStock_
14 << ", price: " << p.price_ << '\n';
15}
16
17struct Time
18{
19 int hour;
20 int minute;
21};
22struct Date
23{
24 Time t;
25 int year;
26 int month;
27 int day;
28};
29
30int main()
31{
32 Product p{.name_ = "box", .inStock_{true}};
33 Print(p);
34
35 Date d{.t{.hour = 10, .minute = 35}, .year = 2050, .month = 5, .day = 10};
36
37 // pass to a function:
38 Print({.name_ = "tv", .inStock_{true}, .price_{100.0}});
39
40 // not all members used:
41 Print({.name_ = "car", .price_{2000.0}});
42}
评论