-
括号初始化
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)
- 变量初始化:
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扩充了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作为参数的。需要额外注意这一点!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)