您的位置 首页 java

C++20 新特性(4):使用圆括号的多个类成员变量初始化

使用圆括号的多个类成员变量初始化

C++ 20 中对于类成员变量的初始化,增加了支持圆括号的多个类成员变量的初始化,具体的使用方式为:

 #include <iostream>
using std::cout, std::endl;

struct SA
{
    int m_a;
    int m_b = 2;
};

struct SC
{
    int m_c;
    struct SA m_d;
};

int main( int argc, char * argv[] )
{
    struct SA a1( 1,  3 );     // <1> 圆括号初始化,不需要显式构造函数
    struct SA a2( 2 );          // <2> 可以值初始化一部分成员变量
    struct SC c1( 5, { 2 } );  // <3> 支持嵌套初始化,不过里面的对象不能用圆括号,要用大括号
    cout << a1.m_a << " " << a1.m_b << endl;
    cout << a2.m_a << " " << a2.m_b << endl;
    cout << c1.m_c << " " << c1.m_d.m_a << " " << c1.m_d.m_b << endl;
    return 0;
}  

传统的圆括号的初始化,其实是相当于调用构造函数进行初始化,默认的构造函数是不带参数的,或者拷贝构造函数带一个相同的类作为参数,如果类本身支持从其他类到本类的类型转换,也支持使用,这种是仅限于一个参数。其他情况,都需要显式定义带不同参数的构造函数。

而现在有了新增的圆括号的初始化方式后,可以不需要显式定义构造函数了。

编译和运行的结果为

 [smlc@test code]$ g++ -std=c++20 a4.cpp
[smlc@test code]$ ./a.out 
1 3
2 2
5 2 2
[smlc@test code]$ g++ -std=c++17 a4.cpp
a4.cpp: In function 'int main(int, char**)':
a4.cpp:32:22: error: no matching function for call to 'SA::SA(int, int)'
   32 |  struct SA a1( 1,  3 );
      |                      ^
a4.cpp:4:8: note: candidate: 'SA::SA()'
    4 | struct SA
      |        ^~
a4.cpp:4:8: note:   candidate expects 0 arguments, 2 provided
a4.cpp:4:8: note: candidate: 'constexpr SA::SA(const SA&)'
a4.cpp:4:8: note:   candidate expects 1 argument, 2 provided
a4.cpp:4:8: note: candidate: 'constexpr SA::SA(SA&&)'
a4.cpp:4:8: note:   candidate expects 1 argument, 2 provided
a4.cpp:33:18: error: no matching function for call to 'SA::SA(int)'
   33 |  struct SA a2( 2 );
      |                  ^
a4.cpp:4:8: note: candidate: 'SA::SA()'
    4 | struct SA
      |        ^~
a4.cpp:4:8: note:   candidate expects 0 arguments, 1 provided
a4.cpp:4:8: note: candidate: 'constexpr SA::SA(const SA&)'
a4.cpp:4:8: note:   no known conversion for argument 1 from 'int' to 'const SA&'
a4.cpp:4:8: note: candidate: 'constexpr SA::SA(SA&&)'
a4.cpp:4:8: note:   no known conversion for argument 1 from 'int' to 'SA&&'
a4.cpp:34:25: error: no matching function for call to 'SC::SC(int, <brace-enclosed initializer list>)'
   34 |  struct SC c1( 5, { 2 } );
      |                         ^
a4.cpp:10:8: note: candidate: 'SC::SC()'
   10 | struct SC
      |        ^~
a4.cpp:10:8: note:   candidate expects 0 arguments, 2 provided
a4.cpp:10:8: note: candidate: 'constexpr SC::SC(const SC&)'
a4.cpp:10:8: note:   candidate expects 1 argument, 2 provided
a4.cpp:10:8: note: candidate: 'constexpr SC::SC(SC&&)'
a4.cpp:10:8: note:   candidate expects 1 argument, 2 provided  

C++17 及之前的标准,不支持圆括号初始化,所以会报错,找不到对应的构造函数。

使用圆括号和大括号进行初始化的对比

圆括号和大括号都能进行初始化,但细节上有一些差异。

大括号初始化时,不允许进行缩窄转换,例如从 double 转换成 int ,而圆括号初始化支持:

 struct SD
{
    int m_a;
    int m_b;
};
struct SD
{
    int m_a;
    int m_b;
};
struct SD d1 { 3.0, 3 };  // <1> Error,大括号初始化不支持double到int的缩窄转换
struct SD d2 ( 3.0, 3 );  // <2> OK,圆括号初始化支持double到int的缩窄转换  

大括号初始化时,引用临时对象,会延长临时对象的生命周期,与当前对象一样长。而圆括号初始化不会延长临时对象的生命周期,可能会导致悬空引用。

 struct SE 
{
    int m_a;
    int && m_r;
};
int func();
int n = 3;
struct SE e1 { 1, func() };   // <1> OK,func()产生的临时对象的生命周期会延长
struct SE e2 ( 1, func() );   // <2> 编译通过,运行潜在问题,func()产生的临时对象提前销毁,m_r 成为悬空引用
struct SE e3 ( 1, std::move( n ) );  // <3> OK,使用 std::move() 来进行右值引用,转移所有权,  

【往期回顾】

文章来源:智云一二三科技

文章标题:C++20 新特性(4):使用圆括号的多个类成员变量初始化

文章地址:https://www.zhihuclub.com/198025.shtml

关于作者: 智云科技

热门文章

网站地图