条款7 辨别使用()与{}创建对象的差别

基础知识

  目前已知有如下的初始化方式:

int x();
int y = ;
int z{};
int z = {}; // the same as above

  在以“=”初始化的过程中没有调用赋值运算,如下例所示:

Widget w1; // default ctor
Widget w2 = w1; // copy ctor
w1 = w2; // assignment, operator =

  还可以用来初始化:

class Widget {
int x{}; // fine
int y = ; // fine
int z(); // error
}; std::atomic<int> ai1{}; // fine
std::atomic<int> ai2(); // fine
std::atomic<int> ai3 = ; // error

  在构造函数中,()与{}在不含有的std::initializer_list的时候意义相同。但是如果出现std::initializer_list,则使用{}初始化语法的时候更倾向调用重载过后的函数。甚至那些拷贝和移动构造函数也会被劫持,例如:

class Widget {
public:
Widget(int i, bool b);
Widget(int i, double d);
Widget(std::initializer_list<long double> il);
operator float() const;
}; Widget w5(w4); // copy ctor
Widget w6{w4}; // w4 -> float -> initializer_list<long double>

  std::initializer_list构造函数太强烈, 以致最优的匹配函数不是它,也会因缩窄匹配而错误:

Widget(std::initializer_list<bool> il);

Widget w{, 5.0}; // error, narrowing conversions

  只有在不能通过转换匹配的情况下,编译器才查找原来的函数:

Widget(std::initializer_list<std::string> il);

Widget w{, 5.0}; // OK

  在空值的情况下:

Widget w1; // default ctor
Widget w2{}; // default ctor
Widget w3(); // most vexing parse! function

总结

  • {}初始化时最多使用的初始化语法,它不能进行缩窄转换(narrowing conversion),并且对一些令人烦恼的解析(most vexing parse)免疫
  • 在构造函数重载解析过程中,{}初始化优先匹配std::initializer_list,即使其他构造函数更匹配
  • 使用()或者{}的方式创建std::vector<numeric type>会有很大的不同
  • 在模板中选择()或{}方式创建对象是一个挑战

[Effective Modern C++] Item 7. Distinguish between () and {} when creating objects - 辨别使用()与{}创建对象的差别的更多相关文章

  1. [Effective Modern C++] Item 6. Use the explicitly typed initializer idiom when auto deduces undesired types - 当推断意外类型时使用显式的类型初始化语句

    条款6 当推断意外类型时使用显式的类型初始化语句 基础知识 当使用std::vector<bool>的时候,类型推断会出现问题: std::vector<bool> featu ...

  2. [Effective Modern C++] Item 5. Prefer auto to explicit type declarations - 相对显式类型声明,更倾向使用auto

    条款5 相对显式类型声明,更倾向使用auto 基础知识 auto能大大方便变量的定义,可以表示仅由编译器知道的类型. template<typename It> void dwim(It ...

  3. [Effective Modern C++] Item 4. Know how to view deduced types - 知道如何看待推断出的类型

    条款四 知道如何看待推断出的类型 基础知识 有三种方式可以知道类型推断的结果: IDE编辑器 编译器诊断 运行时输出 使用typeid()以及std::type_info::name可以获取变量的类型 ...

  4. [Effective Modern C++] Item 3. Understand decltype - 了解decltype

    条款三 了解decltype 基础知识 提供一个变量或者表达式,decltype会返回其类型,但是返回的内容会使人感到奇怪. 以下是一些简单的推断类型: ; // decltype(i) -> ...

  5. [Effective Modern C++] Item 2. Understand auto type deduction - 了解auto类型推断

    条款二 了解auto类型推断 基础知识 除了一处例外,auto的类型推断与template一样.存在一个直接的从template类型推断到auto类型推断的映射 三类情况下的推断如下所示: // ca ...

  6. [Effective Modern C++] Item 1. Understand template type deduction - 了解模板类型推断

    条款一 了解模板类型推断 基本情况 首先定义函数模板和函数调用的形式如下,在编译期间,编译器推断T和ParamType的类型,两者基本不相同,因为ParamType常常包含const.引用等修饰符 t ...

  7. Effective Modern C++ Item 27:重载universal references

    假设有一个接收universal references的模板函数foo,定义如下: template<typename T> void foo(T&& t) { cout ...

  8. Effective Modern C++ Item 37:确保std::thread在销毁时是unjoinable的

    下面这段代码,如果调用func,按照C++的标准,程序会被终止(std::terminate) void func() { std::thread t([] { std::chrono::micros ...

  9. Effective Modern C++ 42 Specific Ways to Improve Your Use of C++11 and C++14

    Item 1: Understand template type deduction. Item 2: Understand auto type deduction. Item 3: Understa ...

随机推荐

  1. UIScrollView 滑动试图

    UIScrollView --->UIView //创建UIScrollView testScrollView=[[UIScrollView alloc]init]; testScrollVie ...

  2. linux android ndk

    Android调用so库, so库是c语言编写, 在linux 64位系统+ndk(32位)生成 lib*.so (32位) 1. 所需软件环境: 1)so库开发环境 操作系统: Redhat Ser ...

  3. 高性能PHP日志插件--Seaslog

    日志系统作为记录系统运行的信息,包括 用户输入,安全日志等,日志系统是不能影响用户的使用. 为什么需要记录日志? 既然日志系统增加了整个系统的开销,为什么我还需要它,这是因为日志能帮我们记录运行的很多 ...

  4. ruby更换为淘宝的源

    我们在使用gem更新的时候,经常会为速度抓狂,其实gem默认的源是https://rubygems.org,比较慢众所周至的原因了. 可以将源更换到国内的taobao源 查看当前有的源 gem sou ...

  5. [原]C++程序示例:涉及到抽象类、继承…

    C++复习题. 有助于理解: .h与.cpp分离 基类.派生类.抽象类 多态.纯虚函数 对象指针.引用 派生类使用基类的构造函数 ... =============================== ...

  6. Python之路第十三天,高级(7)-详述数据库一对多,多对多表关系的设计以及如何查询

    一对多表设计和查询方法 #!/usr/bin/env python3 # Author: Zhangxunan from sqlalchemy import create_engine from sq ...

  7. IIS6.0架构概览(翻译)

    IIS6.0提供一个重新设计的万维网发布服务(World Wide Web Publishing Service)架构,可以帮助你为你的网站构建更好的性能.可靠.可扩展性(scalability),无 ...

  8. js的eval方法

    eval方法: 检查JScript代码,并且执行. 语法: eval(codeString); 参数: codeString是必选项,参数是包含有效的JScript代码的字符串值,这个字符串值将由JS ...

  9. C语言之预处理命令

    /**************************************************************************** Title:C之预处理命令 Time:201 ...

  10. JS中各种宽度、高度、位置、距离总结

    1.window.screen 浏览器与屏幕的距离,screenX(screenLeft),screenY(screenTop) 2.window.scrollTo(x,y) 将纵向滚动条移动到相对于 ...