c++11之初始化列表

一、前言

     C++的学习中,我想每个人都被变量定义和申明折磨过,比如我在大学笔试过的几家公司,都考察了const和变量,类型的不同排列组合,让你区别有啥不同。反正在学习C++过程中已经被折磨惯了,今天再来看看重温下那段“辉煌的历史”。先来看一段代码:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Player pa;                              // (a)  
  2. Player pb();                            // (b)  
  3. Player pc = Player();                   // (c)    
  4. Player pd(Player());                    // (d)      
  5. pd = Player()                           // (e)  
a,b,c,d 都是申明一个变量,a 很容易理解就是申明一个变量,b第一感觉是函数申明,其实不是,而是对象申明。对于c以为是调用了operator= 赋值运算吧?完全不是,而是先生成一个对象,然后调用Player的拷贝构造函数,生成对象pc。d和c是一样的。e才是真正调用赋值操作。是不是已经被这各式各样的对象申明搞的晕头专向了。现在C++11初始化列表正式登场。

二、简介

     在看C++11初始化前,先来回忆一下C语言中的结构体初始化,代码如下:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include <iostream>  
  2.   
  3. struct Player{  
  4.     int id;  
  5.     const char* name;  
  6. };  
  7.   
  8. int main() {  
  9.     Player player = {10001, "c++"};  
  10.     printf("%d, %s\n", player.id, player.name);  
  11. }  

     结构体变量可以列表初始化,非常方便。C++11引入了初始化列表来初始化变量和对象。

三、如何使用

     1、系统内置类型

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. int ia{1};                // (a)  
  2. int ib = {1};             // (b)     
  3. int ic(1);                // (c)   
  4. int id = 1;               // (d)  

    很明显,还是d 更符合习惯。
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. std::vector<int> va{1, 2, 3};          // (a)  
  2. std::vector<int> vb = {1, 2, 3};       // (b)      
  3. std::vector<int> vc(1, 10);            // (c)     
  4. std::vector<int> vd{1, 10};            // (d)    
 
    通过初始化列表可以弥补c中只能初始化相同数字的问题。在使用中c和d不要混淆了。
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. std::pair<intconst char*> getPlayer() {  
  2.      return {10001, "c++"};  
  3.  }  
  4. std::map<intconst char*> players = {{10001, "c++"}, {10002, "java”}};  
    
    还可以返回pair类型,初始化map都是可以的。

    2、自定义类型

    对于单个参数初始化,类型匹配构造函数,不需要自定义构造函数。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Player pa{};                    // (a)  
  2. Player pb;                      // (b)    
  3. Player pc();                    // (c)  
  4. Player pd(b);                   // (d)  
  5. Player pe = b;                  // (e)  
  6. Player pf = {b};                // (f)  



    对于上面几种变量初始化,推荐a, 如果是带参数的构造函数,推荐b,若果是不带参数的构造函数。

     3、如果是自己想实现初始化列表构造函数,拷贝函数,赋值函数,需要包含initializer_list 这个头文件。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. class MyClass{  
  2. public:  
  3.     MyClass(int a):a_(a){  
  4.         std::cout << "normal initializer list\n";  
  5.     }  
  6.   
  7.     MyClass(std::initializer_list<int> a):b_(a) {  
  8.         std::cout << "initializer list constructor\n";  
  9.     }  
  10.   
  11.     MyClass(MyClass& my) {  
  12.         std::cout << "copy constructor\n";  
  13.         this->a_ = my.a_;  
  14.         this->b_ = my.b_;  
  15.     }  
  16.   
  17.     MyClass& operator=(MyClass& my) {  
  18.         std::cout << "operator = constructor\n";  
  19.         this->a_ = my.a_;  
  20.         this->b_ = my.b_;  
  21.         return *this;  
  22.     }  
  23. private:  
  24.     int a_;  
  25.     std::initializer_list<int> b_;  
  26. };  


这是自定义类,带有初始化列表构造函数的类,下面来练习下学过的类相关C++知识:
[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. MyClass ma{1};               // (a)  
  2. MyClass mb = {1, 2, 3};      // (b)  
  3. MyClass mc(2);               // (c)  
  4. MyClass md = b;              // (d)  
  5. MyClass me(c);               // (e)  
  6. MyClass mf{e};               // (f)  
  7. auto l{2, 2, 3,3};  
  8. MyClass mh{l};               // (e)  
  9. 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类型,不可转换

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值