【C++】初始化列表构造函数VS普通构造函数
普通构造函数VS初始化列表构造函数
初始化列表构造函数最优先匹配问题
对于一个类而言,只要其中包含有初始化列表的构造函数,编译器在编译使用{}语法的构造时会最倾向于调用初始化列表构造函数,哪怕做类型转换也在所不惜,哪怕有类型最佳匹配的普通构造函数或移动构造函数也会被劫持
class Widget {
public:
Widget(int i, bool b);
Widget(int i, double d);
Widget(std::initializer_list<long double> il);
operator float() const;
};
Widget w1(10, true); // 使⽤小括号初始化
//调⽤第⼀个构造函数
Widget w2{10, true}; // 使⽤花括号初始化
// 调⽤第三个构造函数
// (10 和 true 转化为long double)
Widget w3(10, 5.0); // 使⽤小括号初始化
// 调⽤第二个构造函数
Widget w4{10, 5.0}; // 使⽤花括号初始化
// 调⽤第三个构造函数
// (10 和 5.0 转化为long double)
Widget w5(w4); // 使⽤小括号,调⽤拷⻉构造函数
Widget w6{w4}; // 使⽤花括号,调⽤std::initializer_list构造函数
Widget w7(std::move(w4)); // 使⽤小括号,调⽤移动构造函数
Widget w8{std::move(w4)}; // 使⽤花括号,调⽤std::initializer_list构造函数
编译器这种热衷于把括号初始化与初始化列表构造函数匹配的行为,会导致一些莫名其妙的错误
class Widget {
public:
Widget(int i, bool b);
Widget(int i, double d);
Widget(std::initializer_list<bool> il); // element type is now bool
… // no implicit conversion funcs
};
Widget w{10, 5.0}; //错误!要求变窄转换,int(10)double(5.0)无法转换为bool类型
只有在没有办法把{}中实参的类型转化为初始化列表时,编译器才会回到正常的函数决议流程中
⽐如我们在构造函数中⽤std::initializer_list<std::string>代替std::initializer_list<bool> ,这时⾮std::initializer_list构造函数将再次成为函数决议的候选者,因为没有办法把int和bool转换为std::string:
class Widget {
public:
Widget(int i, bool b);
Widget(int i, double d);
Widget(std::initializer_list<std::string> il);
…
};
Widget w1(10, true); // 使⽤小括号初始化,调⽤第⼀个构造函数
Widget w2{10, true}; // 使⽤花括号初始化,调⽤第⼀个构造函数
Widget w3(10, 5.0); // 使⽤小括号初始化,调⽤第⼆个构造函数
Widget w4{10, 5.0}; // 使⽤花括号初始化,调⽤第⼆个构造函数
{}空初始化列表会发生什么
假如{}内是空的,类中既有默认构造函数,也有初始化列表构造函数,此时{}会被视为没有实参,而不是一个空的初始化列表,因此会调用默认构造函数。如果就是想调用初始化列表构造函数,这应该使用{{}}的方式
class Widget {
public:
Widget();
Widget(std::initializer_list<int> il);
...
};
Widget w1; // 调⽤默认构造函数
Widget w2{}; // 同上
Widget w3(); // 最令⼈头疼的解析!声明⼀个函数
Widget w4({}); // 调⽤std::initializer_list
Widget w5{{}}; // 同上
初始化列表带来的vector的坑
std::vector<int> v1(10, 20); //使⽤⾮std::initializer_list
//构造函数创建⼀个包含10个元素的std::vector
//所有的元素的值都是20
std::vector<int> v2{10, 20}; //使⽤std::initializer_list
//构造函数创建包含两个元素的std::vector
//元素的值为10和20
初始化列表构造函数问题带来的两点启示
- 作为类库作者,如果在构造函数中重载了一个或多个初始化列表构造函数,要考虑用户使用{}初始化的情况,最好避免类似std::vector中的情况。应该尽可能做到用户无论用小括号还是花括号进行初始化都不会产生区别。一定要慎重考虑新出现的初始化列表构造函数对其他构造函数的影响!!!
- 作为类库使用者,必须认真的考虑小括号和花括号之间选择创建对象的方式,最好选择其中一个从一而终
【C++】初始化列表构造函数VS普通构造函数的更多相关文章
- C++-什么时候需要在类的构造函数中使用初始化列表
1,如果基类没有default构造函数,则意味着其不能自己初始化.如果其被派生,派生类的构造函数要负责调用基类的构造函数,并传递给它需要的参数.下例中Base 2,如果类成员没有默认构造函数.下例中E ...
- c++ 关于类构造函数的初始化列表
除了性能问题之外,有些时场合初始化列表是不可或缺的,以下几种情况时必须使用初始化列表 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面 引用类型,引用必须在定义的时候初始化,并且不能重 ...
- 【校招面试 之 C/C++】第1题 为什么优先使用构造函数的初始化列表
1.首先看一个例子: #include<iostream> using namespace std; class Test1 { public: Test1() // 无参构造函数 { c ...
- C++ 构造函数_初始化列表
构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式.例如: class Student { public: //构造函数初始化列表 Stude ...
- C++初阶(类的访问权限以及封装+this指针+构造函数+析构函数+拷贝构造函数+参数列表+友元+内部类)
面向过程与面向对象 C语言是面向过程的,关注的是过程(函数),分析出求解问题的步骤,通过函数调用逐步解决问题. C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成. ...
- C++类的成员初始化列表的相关问题
在以下四中情况下,要想让程序顺利编译,必须使用成员初始化列表(member initialization list): 1,初始化一个引用成员(reference member): 2,初始化一个常量 ...
- c++,初始化列表
类对象的构造顺序是这样的: a.分配内存,调用构造函数时,隐式/显示的初始化各数据成员 b.进入构造函数后在构造函数中执行一般计算 1.初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内 ...
- C++ 初始化列表(转)
转载自:http://www.cnblogs.com/graphics/archive/2010/07/04/1770900.html 何谓初始化列表 与其他函数不同,构造函数除了有名字,参数列表和函 ...
- C++: 类成员初始化列表语法
类的成员初始化列表的初始化的基本语法,类的构造函数还可以运用此语法为其变量初始化: class Class { private: int a; int b; char ch; public: Cl ...
- C++ 成员初始化列表
1.什么是成员初始化列表 #include<iostream> #include<string> using namespace std; class Weapon { pri ...
随机推荐
- 在 Sitecore 里使用 Solr 搜索 SortOrder 关联的 Item
在 C# 使用 Solr 搜索 sitecore 的配置信息文件可直接丢进 <Instance>\App_Config 下,sitecore 会自动检测配置文件更新并加载到内存中. 通常情 ...
- 网络安全(中职组)-B模块:Web安全应用-2
Web安全应用-2 任务环境说明: √ 服务器场景: match_win03-3-1(关闭链接) √ 服务器场景操作系统:Windows Server 2003 1. 使用渗透机Kali Linux, ...
- 干货来袭!3天0基础Python实战项目快速学会人工智能必学数学基础全套(含源码)(第3天)概率分析篇:条件概率、全概率与贝叶斯公式
第1天:线性代数篇:矩阵.向量.实战编程 第2天:微积分篇:极限与导数.梯度下降.积分.实战编程 第3天:概率分析篇:条件概率与全概率.贝叶斯公式.实战项目 目录 前言 一.概率与机器学习 1.1 概 ...
- Gym 101490K Safe Racing (dp转换, 超超超级详细,包你看懂)
题意:给你一个长为L的圆形跑道,让你放置警示牌,相邻两个警示牌相隔距离不能超过S,让你求有多少种方案数放置.数据L,S都是1e6. 来个例子:L = 13, S = 5.一个圈表示长度为1. 思路:因 ...
- EF Code 如何应对高并发
1.高并发的情况,时常会发生数据不稳定的情况 在看本节内容之前,请先看上一章SqlServer 高并发的情况下,如何利用锁保证数据的稳定性 本节内容,也是具体讨论如何在EF中实现这些操作 2.场景模拟 ...
- 控制论个人学习笔记-线性系统的校正方法&现代控制论基础
note 2020-08-05搬运 下面的内容来自(我的CSDN博客)[https://blog.csdn.net/weixin_45183579/article/details/105201314] ...
- Spring 的核心组件详解
Spring 总共有十几个组件,但是真正核心的组件只有三个:Core.Context 和 Bean.它们构建起了整个 Spring的骨骼架构,没有它们就不可能有 AOP.Web 等上层的特性功能. 一 ...
- 设计模式(二十九)----综合应用-自定义Spring框架-Spring IOC相关接口分析
1 BeanFactory解析 Spring中Bean的创建是典型的工厂模式,这一系列的Bean工厂,即IoC容器,为开发者管理对象之间的依赖关系提供了很多便利和基础服务,在Spring中有许多IoC ...
- 这可能是最全面的Spring面试题总结了
Spring是什么? Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架. Spring的优点 通过控制反转和依赖注入实现松耦合. 支持面向切面的编程,并且把应用业务逻辑和系统 ...
- pandas之读取文件
当使用 Pandas 做数据分析的时,需要读取事先准备好的数据集,这是做数据分析的第一步.Panda 提供了多种读取数据的方法: read_csv() 用于读取文本文件 read_json() 用于读 ...