美文网首页
Effective Modern C++ 学习笔记3——()和{

Effective Modern C++ 学习笔记3——()和{

作者: 拔丝圣代 | 来源:发表于2023-04-01 14:49 被阅读0次

    几个例子探讨区别

    C++中初始化方式有很多种,下面用几个例子来对比其区别。

    1. 以下3种初始化方式合法吗?
    int x = 1.0;
    int x(1.0);
    int z{1.0};
    

    答案:x和y的初始化合法,z的初始化不合法。

    原因:大括号初始化内建类型时,禁止隐式窄化类型转换。

    所谓窄化类型转换,指的是类型转换可能丢失精度,比如double转为int;反之则允许。

    1. 下面几行声明的是对象还是函数?
    // 假设已有class Widget的定义
    Widget w1;
    Widget w2();
    Widget w3(1);
    Widget w4{};
    Widget w5{1};
    

    答案:w2声明了一个函数,返回值类型为Widget,其他几种都声明了一个Widget对象。

    这就是most vexing parse。对比w2与w3,w3传入一个int类型参数,调用的是Widget(int)这个构造函数;如果想要调用Widget的默认构造函数,而去掉括号中的参数,却声明了一个返回Widget的函数。

    而将小括号换成大括号,w4和w5则可以避免这个问题,声明的一定是对象而非函数。

    1. 下面的代码分别声明了什么样的vector?
    std::vector<int> v1(10,20);
    std::vector<int> v2{10,20};
    

    答案:v1长度为10,所有元素为20;v2长度为2,元素分别为10, 20。

    为什么这里用小括号和大括号有如此大的区别?可以简单的理解为vector包含这样两个构造函数:

    vector(int, int);
    vector(std::initializer_list);
    

    而当使用大括号初始化时,总是会优先匹配std::initializer_list类型的参数

    模板中如何选择?

    在平时的代码中,我们一般可以选择其中一种作为默认,另一种只在必要时使用。

    而在模板的编写中,这是一个非常头疼的问题。

    例如,想要创建一个模板,能够以任意数量参数创建任意类型对象,可以这样写:

    template<typename T, typename... Ts>
    void doSomeWork(TS&&.. params) {
      T localObject(std::forward<Ts>(params)...); // 选择采用小括号
      T localObject{std::forward<Ts>(params)...); // 或选择采用大括号
    }
    

    那么,结合上面的例子,当我们这样使用时:

    doSomeWork<std::vector<int>>(10, 20);
    

    到底是创建了长度为10,每个值为20的vector对象,还是创建了长度为2,值分别为10、20的vector对象呢?

    这便取决于doSomeWork内部实现中,到底使用的是小括号还是大括号。

    这正是std::make_unique和std::make_shared所面临的问题,目前的实现是,内部使用的小括号。

    相关文章

      网友评论

          本文标题:Effective Modern C++ 学习笔记3——()和{

          本文链接:https://www.haomeiwen.com/subject/oinkddtx.html