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

news/2024/7/5 1:56:23

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

http://lihuaxi.xjx100.cn/news/269848.html

相关文章

《大话西游》20年后重映(附影评:《大话西游》你真的看懂了吗?)

2014-10-25 02:43:24 来源: 北京日报(北京)本报讯 &#xff08;记者 周南焱&#xff09;“电影里的台词差点儿都能背&#xff0c;但在影院里再看还是会笑。看到最后紫霞仙子死的时候。还是忍不住落泪&#xff01;”昨天下午&#xff0c;经典老片《大话西游》在海航活力天宝影城…

php libev pthreads,libuv 与 libev 的对比

05 January 2013libuv和libev&#xff0c;两个名字相当相近的 I/O Library&#xff0c;最近有幸用两个 Library 都写了一些东西&#xff0c;下面就来说一说我本人对两者共同与不同点的主观表述。高性能网络编程这个话题已经被讨论烂了。异步&#xff0c;异步&#xff0c;还是异…

跨平台网络游戏趋势和优势

跨平台网络游戏趋势和优势 前几年还是网页游戏蓬勃发展的状态&#xff0c;就有分析指出从明年开始网页游戏市场已经饱和&#xff0c;想想几年前客户端游戏也是同样的窘境&#xff0c;如果将桌面、移动设备、网页统称一个词汇的话&#xff0c;那就是终端&#xff0c;现在各种的终…

计算摄影 | 计算机如何学会自动裁剪图片(自动构图)?

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶”重磅干货&#xff0c;第一时间送达1 自动构图基础1.1 什么是构图自动裁剪用摄影的话语来说&#xff0c;就是自动构图。构图来源于绘画&#xff0c;最初指绘画时根据题材和主题思想的要求&#xff0c;把要表…

阿里云蒋江伟:我们致力于为世界提供70%的算力 | 凌云时刻

导读&#xff1a;6月9日&#xff0c;2020阿里云峰会在云端召开&#xff0c;阿里巴巴合伙人、阿里云智能基础产品事业部高级研究员蒋江伟出席峰会并做了题为《新基建&#xff0c;新算力&#xff1a;阿里云基础设施算力全新升级》的重磅发布。&#xff08;以下内容为演讲实录&…

关于Redis缓存,这3个问题一定要知道!

点击上方蓝色“方志朋”&#xff0c;选择“设为星标”回复“666”获取独家整理的学习资料&#xff01;来源&#xff1a;https://4m.cn/e3JwR最近都没看Redis&#xff0c;现在回来温习下&#xff0c;现在从Redis的三大缓存开始重新探一探有多深有多浅(^▽^)让我来开始知识的醍醐…

第十一周作业关于json

json文件的实例&#xff1a; json文件&#xff1a;{ "name":"王小二"&#xff0c; "age":25.2, "birthday":"1990-01-01", "school":"蓝翔", "major(技能)"&#xff1a;["理发",&q…

「留光」1小时:中科大让我们离「量子U盘」又近了一步

视学算法报道转载自&#xff1a;机器之心编辑&#xff1a;张倩、小舟「简单来说&#xff0c;我们就是用一块晶体把光『存起来』&#xff0c;一个小时后取出来发现&#xff0c;它的相位、偏振等状态信息还保存得很好。」存储器的功能就是把信息存储起来&#xff0c;直到需要用到…