c++11 统一初始化

c++11 统一初始化,第1张

c++11 统一初始化 一、c++98/03的初始化方式
  • 括号初始化

    int a(2);//ctor(尽管这个例子貌似不是很恰当)
    int b(a);//c-ctor
    
  • 列表初始化:

    //c++98/03的列表初始化用于初始化数组
    int arr1[3] = { 1, 2, 3 };
    int arr2[] = { 1, 3, 2, 4 };
    //c++98/03的列表初始化用于初始化结构体变量(貌似不太常用)
    struct A{
        int a;
        int b;
        int c;
    };
    A a{1,2,3};//但这样做明显有溢出危险啊。。(比如把A::c的类型换成char)
    
二、c++11的统一初始化
  • 变量初始化:
class A{
public:
    A()=default;
    A(int a):a_(a){}
    A(int a,int b):a_(a){}
    int a_;
};
int main(){
    A aa1(2);//c++98的写法,有时候小括号容易与函数冲突了,所以c++11之后最好不要这么用
    A aa2{2};//这种写法是推荐的,效果和aa1一样
    A aa3={2};//这种写法容易引起歧义,最好不要写,但和aa2的效果是一样的
    A aa4{2,3};
}
  • new对象初始化:

    int* a=new int{2};//和小括号一样
    int* a=new int[2]{1,2};//c++11可以直接初始化动态数组了
    
  • 构造临时对象:

    class A{
    public:
        A()=default;
        A(int a):a_(a){}
        A(int a,int b):a_(a){}
        int a_;
    };
    A func(){
        return {2,3};
    }
    
三、c++11的初始化列表(std::initializer_list)

c++11扩充了c++98/03的初始化列表,进化成了std中的一个泛型类。在初始化vector等标准库容器时很常喷到它。

但在初始化中,std::initializer_list的出现往往会引起出乎意料的情况:

class A{
public:
    A()=default;
    A(bool a):a_(a){}
    A(std::initializer_list<int> list):a_(list.size()){}
    int a_;
};
int main(){
    A aa1(false);
    A aa2{false};
    
    std::cout<<aa1.a_<<std::endl;
    std::cout<<aa2.a_<<std::endl;
}

以上运行结果:

zkcc@LAPTOP-OHBI7I8S:~/mytest$ g++ test_init.cc -o test_init && ./test_init
0
1

这说明了一个很关键的问题:c++貌似更倾向于将统一初始化写法与std::initializer_list匹配,哪怕另外一条路径有着更匹配的类型。

在上面的代码中, A aa2{false};有2条可能的路径:
1. 将{false}看成bool型的统一初始化,匹配第一个构造函数
2. 将{false}强转成std::initializer_list,匹配第二个构造函数

明显感觉第一个构造函数更匹配一些嘛,也不需要强转,但std::initializer_list就是很霸道,哪怕强转也要匹配!

因此,在使用统一初始化的时候,必须注意初始化的类型构造函数中是否有std::initializer_list作为参数的。需要额外注意这一点!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/872729.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存