一、前言
C++的学习中,我想每个人都被变量定义和申明折磨过,比如我在大学笔试过的几家公司,都考察了const和变量,类型的不同排列组合,让你区别有啥不同。反正在学习C++过程中已经被折磨惯了,今天再来看看重温下那段“辉煌的历史”。先来看一段代码:- Player pa; // (a)
- Player pb(); // (b)
- Player pc = Player(); // (c)
- Player pd(Player()); // (d)
- pd = Player() // (e)
二、简介
在看C++11初始化前,先来回忆一下C语言中的结构体初始化,代码如下:- #include <iostream>
- struct Player{
- int id;
- const char* name;
- };
- int main() {
- Player player = {10001, "c++"};
- printf("%d, %s\n", player.id, player.name);
- }
结构体变量可以列表初始化,非常方便。C++11引入了初始化列表来初始化变量和对象。
三、如何使用
1、系统内置类型
- int ia{1}; // (a)
- int ib = {1}; // (b)
- int ic(1); // (c)
- int id = 1; // (d)
- std::vector<int> va{1, 2, 3}; // (a)
- std::vector<int> vb = {1, 2, 3}; // (b)
- std::vector<int> vc(1, 10); // (c)
- std::vector<int> vd{1, 10}; // (d)
通过初始化列表可以弥补c中只能初始化相同数字的问题。在使用中c和d不要混淆了。
- std::pair<int, const char*> getPlayer() {
- return {10001, "c++"};
- }
- std::map<int, const char*> players = {{10001, "c++"}, {10002, "java”}};
还可以返回pair类型,初始化map都是可以的。
2、自定义类型
对于单个参数初始化,类型匹配构造函数,不需要自定义构造函数。
- Player pa{}; // (a)
- Player pb; // (b)
- Player pc(); // (c)
- Player pd(b); // (d)
- Player pe = b; // (e)
- Player pf = {b}; // (f)
对于上面几种变量初始化,推荐a, 如果是带参数的构造函数,推荐b,若果是不带参数的构造函数。
3、如果是自己想实现初始化列表构造函数,拷贝函数,赋值函数,需要包含initializer_list 这个头文件。
- class MyClass{
- public:
- MyClass(int a):a_(a){
- std::cout << "normal initializer list\n";
- }
- MyClass(std::initializer_list<int> a):b_(a) {
- std::cout << "initializer list constructor\n";
- }
- MyClass(MyClass& my) {
- std::cout << "copy constructor\n";
- this->a_ = my.a_;
- this->b_ = my.b_;
- }
- MyClass& operator=(MyClass& my) {
- std::cout << "operator = constructor\n";
- this->a_ = my.a_;
- this->b_ = my.b_;
- return *this;
- }
- private:
- int a_;
- std::initializer_list<int> b_;
- };
这是自定义类,带有初始化列表构造函数的类,下面来练习下学过的类相关C++知识:
- MyClass ma{1}; // (a)
- MyClass mb = {1, 2, 3}; // (b)
- MyClass mc(2); // (c)
- MyClass md = b; // (d)
- MyClass me(c); // (e)
- MyClass mf{e}; // (f)
- auto l{2, 2, 3,3};
- MyClass mh{l}; // (e)
- ma = mb; // (h)
看一下每次调用都输出什么结果,答案在这里:
initializer list constructor
initializer list constructor
normal constructor list
copy constructor
copy constructor
copy constructor
initializer list constructor
operator = constructor
四、为啥需要初始化列表
1、避免类申明对象混淆,区分对待,对于C++为啥有小括号初始化对象这一说,大家可以自行google,看来不管是谁都有犯错误的时候,勇于承认错误还是好同志。
2、在初始化多个变量时方便
3、避免数据切割,因为通过初始化列表是不允许隐式转换的,相关知识可以参考我的这篇文章。
五、注意事项
1、在申明变量的时候,少用小括号,程序可读性更高
2、使用初始化列表防止隐式转换,减少bug
3、通过 {} 返回的对象是const类型,不可转换