专业编程基础技术教程

网站首页 > 基础教程 正文

C++20 新特性(3):指定类成员变量初始化

ccvgpt 2024-10-10 05:03:32 基础教程 82 ℃

指定类成员变量初始化

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

编译和执行结果为:

C++20 新特性(3):指定类成员变量初始化

[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 语法冲突


【往期回顾】

C++ 20 新特性(2):支持位段类型的类成员的直接初始化

C++20新特性(1):前言,废弃数组下标中的逗号表达式

最近发表
标签列表