指定类成员变量初始化
C++ 20 对于类成员变量的初始化,增加了指定类成员变量的初始化方式,这种方式其实在 gcc 中作为扩展很早就提供了,而且 C99 标准中也已经加入类似的语法对结构体(struct)进行初始化。
#include <iostream>
struct SA
{
int m_a;
int m_b;
};
struct SC
{
int m_c = 4;
struct SA m_d;
};
int main( int argc, char * argv[] )
{
struct SA a1 { .m_a = 1, .m_b { 2 } }; // <1> 支持等号或者大括号的初始化方式
struct SA a2 = { .m_b = 3 }; // <2> 可以跳过一些成员变量
struct SC c1 = { .m_d { .m_b = 4 } }; // <3> 可以嵌套,m_c未指定时使用默认值
std::cout << a1.m_a << " " << a1.m_b << std::endl;
return 0;
}
编译和执行结果为:
[foo@test code]$ g++ a3.cpp
[foo@test code]$ ./aout
1 2
3 5
4 3 6
初始化相关的补充说明
传统的初始化方式,需要按顺序列出各个的成员变量的初始化的值,可以不全部列出,后面忽略的成员变量使用默认值初始化,但不能跳过中间的部分成员变量。而且直接列出初始化的值,这些值和具体成员变量的关系是靠顺序来对应,代码上不直观。
而指定类成员变量的初始化的语法,可以跳过中间的部分,只对指定成员变量初始化,其他未指定的成员变量使用默认值初始化。由于每个初始化的值的前面都有成员变量的名称,代码上更加直观。另外,必须要按类成员变量的定义时顺序进行初始化,不能乱序。
这种初始化方式,对于联合体(union)也同样适用,但只能对联合体的任一个成员进行初始化,不能对多个成员变量初始化,当然,对多个成员初始化语义上是矛盾的。写代码不但要语法正确,语义也要清晰。
union UA
{
int m_a = 4; // <1> union只能有一个成员变量有默认初始化值
int64_t m_b;
};
UA u1; // <2> 不指定初始化值,则是使用默认初始化值,本例中是 4
UA u2 { .m_b = 0x103050709LL }; // <3> 指定成员变量的初始化,可以对任意成员变量进行初始化
UA u3 = { 2 }; // <4> 普通的按顺序初始化,只能对第一个元素进行初始化
UA u4 { .m_a = 2, .m_b = 5 }; // <5> Error,不支持对多个成员变量初始化
顺便补充一句,C++ 由于有构造函数等语法,情况会复杂很多,容易产生意想不到的副作用,因此语法上要求严格很多,而 C99 的语法要宽松很多,不过建议即使是写 C 语言代码,最好也按C++ 严格的方式编写。
struct SA
{
int m_a;
int m_b;
};
struct SC
{
int m_c;
struct SA m_d;
};
struct SA a1 = { .m_b = 1, .m_a = 2 }; // C合法,C++不合法,不支持成员变量顺序是乱序
struct SA a2 = { .m_a = 1, 2 }; // C合法,C++不合法,不支持混合使用
struct SC c1 = { .m_d.m_a = 6 }; // C合法,C++不合法,不支持嵌套对象的直接多个圆点连接
int arr[3] = { [1] = 5 }; // C合法,C++不合法,不支持数组成员初始化,这个写法和 lamda 语法冲突
【往期回顾】