• [Effective Modern C++] Item 7. Distinguish between () and {} when creating objects


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

    基础知识

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

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

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

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

      还可以用来初始化:

    class Widget {
        int x{0}; // fine
        int y = 0; // fine
        int z(0); // error
    };
    
    std::atomic<int> ai1{0}; // fine
    std::atomic<int> ai2(0); // fine
    std::atomic<int> ai3 = 0; // 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{10, 5.0}; // error, narrowing conversions

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

    Widget(std::initializer_list<std::string> il);
    
    Widget w{10, 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>会有很大的不同
    • 在模板中选择()或{}方式创建对象是一个挑战
  • 相关阅读:
    转:关于JAVA多线程同步
    转:Java HashMap实现详解
    索引创建规则:
    数据库为什么要分库分表
    [设计模式] javascript 之 桥接模式
    [百度地图] ZMap 与 MultiZMap 封装类说明;
    [设计模式] Javascript 之 外观模式
    [设计模式] javascript 之 代理模式
    [设计模式] javascript 之 装饰者模式
    [设计模式] javascript 之 适配器模式
  • 原文地址:https://www.cnblogs.com/Azurewing/p/4743722.html
Copyright © 2020-2023  润新知