1 统一初始化(Uniform Initialization)

在C++ 11之前,所有对象的初始化方式是不同的,经常让写代码的我们感到困惑。C++ 11努力创造一个统一的初始化方式。
其语法是使用{}和std::initializer_list,先看示例。

    int values[]{ 1, 2, 3 };std::vector<int> v{ 2, 3, 6, 7 };std::vector<std::string> cities{"Berlin", "New York", "London",  "Braunschweig"};std::comples<double> c{4.0, 3.0}; //等价于 c(4.0, 3.0)auto ar = { 1, 2, 3 };  // ar 是一个std::initializer_list<int>类型std::vector<int> v = { 1, 2, 3 };std::list<int> l = { 1, 2, 3 };std::set<int> s = { 1, 2, 3 };std::map<int, std::string> m = { {1, "a"}, {2, "b"} };

2 原理

针对形如"{ 1, 2, 3 }"的参数列表,系统会首先自动调用参数初始化(value initialization),将其转换成一个std::initializer_list,它将用于对变量(可能是简单类型,或者对象类型)初始化。比如"{ 1, 2, 3 }"会首先生成一个std::initializer_list,然后用于生成一个int数组values。c{4.0, 3.0}会生成一个std::initializer_list,然后调用std::comples类的构造函数std::comples(double,double)。
我们通过一个例子来分析具体细节:

    std::vector<int> v{ 2, 3, 6, 7 };
  • 首先,将参数列表{ 2, 3, 6, 7 }转换成std::initializer_list。
    从stl源码中可以看出initializer_list的带参数构造函数是个私有函数,它只能由编译器调用。
    private:iterator          _M_array;size_type         _M_len;// The compiler can call a private constructor.constexpr initializer_list(const_iterator __a, size_type __l): _M_array(__a), _M_len(__l) { }
  • 其次,使用std::initializer_list对象来初始化std::vector类的构造函数。下面是构造函数源码。
      vector(initializer_list<value_type> __l,const allocator_type& __a = allocator_type()): _Base(__a){_M_range_initialize(__l.begin(), __l.end(),random_access_iterator_tag());}

3 未赋值的初始化

如果使用了std::initializer_list,但是没有指定参数值,结果会怎样?直接看示例。

    int i;      //i值未定义int j{};    //j=0int *p;     //p值未定义int *q{};   //q=nullptr

4 在构造函数中显示使用std::initializer_list

我们可以在构造函数中主动使用std::initializer_list,这时外部调用{}初始化时,会优先调用包含std::initializer_list参数的构造函数。请看下例子。

    class P{public:P(int, int){std::cout<<"call P::P(int,int)"<<std::endl;}P(std::initializer_list<int>){std::cout<<"call P::P(initializer_list)"<<std::endl;}};P p(77,5);     // call P::P(int,int)P q{77,5};     // call P::P(initializer_list)P r{77,5,42};  // call P::P(initializer_list)P s = {77, 5}; // call P::P(initializer_list)

5 拒绝隐式调用构造函数

我们知道,C++会先使用{}中的参数生成一个std::initializer_list对象,然后调用赋值对象的构造函数。
有一种特殊情形,我们如果希望对象的某个构造函数必须要被显示调用,如何做到呢?向其中添加一个explicit关键字。在stl库中出现大量的这种使用方式。请看下例:

    class P{public:P(int a, int b){...}explicit P(int a, int b, int c){...}};P x(77,5);    //OKP y{77,5);    //OKP z{77,5,42}; //OKp v = {77,5}; //OK,(implicit type conversion allowed)P w = {77,5,42};//Error,必须要显示调用该构造函数void fp(const P&);fp({47,11});    //OKfp({47,11,3});  //Errorfp(P{47,11});   //OKfp(P{47,11,3}); //OK

6 局限 —— Narrowing Initializations

统一初始化用起来很舒爽,那它有什么局限呢?
有,在一种场景下无法使用,那就是Narrowing Initializations。
Narrowing Initializations,我翻译为“精度截断”。比如float转换为int,double转换为float。统一初始化,完全不允许精度阶段的发生,更进一步,要求参数列表中的所有参数的精度一样。请看以下示例。

    int x1(5.3);    //OK, x1 = 5.3int x3{5.0};    //Errorint x4 = {5.3}; //Errorchar c1{7};     //OKchar c2{99999}; //Errorstd::vector<int> v1{ 1, 2, 4, 5};    //OKstd::vector<int> v2{ 1, 2,3, 4, 5.6};//Error

但是如果实际工程允许精度截断的发生,那么我们应该怎么完成初始化。可以使用()来完成初始化,它会调用赋值操作或者相应的构造函数。

    int x3{5.0};    //Errorint x2(5.2);    //OK, x2 = 5

C++11 带来的新特性 (2)—— 统一初始化(Uniform Initialization)相关推荐

  1. Java 11 正式发布,新特性解读

    Java 11 正式发布,新特性解读 杨晓峰   2018 年 9 月 26 日 话题:Java语言 & 开发 不知不觉 JDK 11 已经发布了,从 9 开始,JDK 进入了让人学不动的更新 ...

  2. 玩玩Xamarin Evolve 2016带来的新特性(三)-Xamarin Workbooks

    编者语:五一祝各位劳动者快乐.今天是该系列文章的最后一篇,当然Evolve 2016还有很多很多的内容,但是我觉得iOS Simulator(for Windows), Xamarin Preview ...

  3. C++11/14/17 新特性总结

    C++11/14/17 新特性总结 initializer_list std::vector<int> vctInts({92, 12, 39, 46, 92, 84, -1, 0, -2 ...

  4. Java 5~11各个版本新特性史上最全总结

    Java 5 Java5开发代号为Tiger(老虎),于2004-09-30发行 特性列表 泛型 枚举 自动装箱拆箱 可变参数 注解 foreach循环(增强for.for/in) 静态导入 格式化( ...

  5. [转]IntelliJ IDEA 2019.3正式发布,给我们带来哪些新特性?

    每篇一句 工欲善其事必先利其器 --<论语·卫灵公> 前言 千呼万唤始出来.自从JetBrains在今年7月24日发布了IDEA 2019.2版本后,从9月份开始我便一直在关注此版本正式版 ...

  6. IntelliJ IDEA 2019.3 正式发布,给我们带来哪些新特性?| CSDN 博文精选

    作者 | _YourBatman 责编 | 屠敏 出品 | CSDN 博客 前言 千呼万唤始出来.自从JetBrains在今年7月24日发布了IDEA 2019.2版本后,从9月份开始我便一直在关注此 ...

  7. Java 11正式发布,新特性解读

    不知不觉 JDK 11 已经发布了,从 9 开始,JDK 进入了让人学不动的更新节奏,对于广大 Java 工程师来说,真是又爱又恨,Java 演进快速意味着它仍将能够保持企业核心技术平台的地位,我们对 ...

  8. Visual Studio 11 九大新特性:图文详解【转】

    转自: [IT168 技术]导读:之前Visual Studio 11开发者预览版发布的消息受到了众多技术人员的关注和讨论.日前Visual Studio 11最新的Beta版本在巴塞罗那正式推出.我 ...

  9. Git 2.7: 一个新的带来许多新特性和性能提升的主要版本

    在2.6版本发布两个月之后,Git 2.7发布.该版本带来了许多新特性以及性能的提升. \\ 本文选取了Git 2.7带来的主要变化: \\ git remote支持get-url子命令,可以显示指定 ...

最新文章

  1. 从零开始MDT2010学习手记(二) 创建共享工作目录
  2. Python-函数的各种器
  3. 搞定系统设计 02:估算的一些方法
  4. usermod命令 、用户密码管理、mkpasswd命令
  5. Centos6.4 编译安装 nginx php
  6. 【C语言】找出1000以内的水仙花数
  7. mysql 存储过程 模糊查询_mysql 分页创建存储过程并实现模糊查询
  8. mysql日志备份的脚本_脚本备份MySQL数据库和binlog日志
  9. js利用CLodop实现打印功能
  10. windows打印机共享给linux,linux使用windows共享打印机
  11. 支付宝转账支付宝转卡(H5飞行模式)
  12. Adobe_Acrobat_Pro_DC_2022.003.20314 下载安装
  13. 活动报名 | 清华大学交叉信息研究院高阳:视觉机器人学习
  14. 史上最全C++排序算法总结!!!(没有之一)
  15. 全球及中国铁路空气弹簧行业研究及十四五规划分析报告(2022)
  16. 东方博宜oj答案c++版
  17. ATAx=0与Ax=0同解
  18. Java x的平方根
  19. 华清远见荣获“华为云精英服务商”资质,助推“华为开发者创新中心”项目落地高校
  20. 调查称多地10%大米镉超标 食物污染链持续多年

热门文章

  1. AI实验室•西安站 教你用人脸识别打造爆款应用
  2. 爆赞,对 volatile 关键字讲解最好的一篇文章!
  3. 到底什么级别才算是高并发?
  4. 有一份华为荣誉证书等你来拿!网络人工智能硬盘异常预测黑客松比赛火热报名中...
  5. 竞赛大杀器xgboost,波士顿房价预测
  6. 从0学人脸识别,我花3小时复现了Eigenfaces For Recognition
  7. 从Google Scholar看各大科技公司的科研水平
  8. 程序员面试时,不小心说了真话…...
  9. 30个Python常用极简代码,拿走就用
  10. 浅谈深度学习混合精度训练