美文网首页
C++ auto 类型推导

C++ auto 类型推导

作者: CharlesZhangCh | 来源:发表于2021-05-30 15:58 被阅读0次

    C++ auto 类型推导规则与模板类型推导类似,两者只有一点不一样。

    前面说过,模板的声明和使用方式如下:

    template<typename T>
    void f(ParamType param);
    
    f(expr);
    

    auto的使用方式如下:

    auto x = 27;
    const auto cx = x;
    const auto& rx = x;
    

    在auto进行类型推导的时候,auto相当于模板里的T,变量类型修饰符相当于ParamType,等号右边的部分相当于expr。例如:

    auto x = 27;
    // 进行x的类型推导,就如同下面的模板类型推导
    template<typename T>
    void func_for_x(T param);
    func_for_x(27);
    // 27是int型,根据上篇文章的推导规则,param是int型,因此x也是int型。
    
    const auto& rx = x;
    // 进行rx的类型推导,就如同下面的模板类型推导
    template<typename T>
    void func_for_rx(const T& param);
    
    func_for_rx(x);
    // x是int型,模板推导出的param类型是const int&,因此rx也是const int&。
    

    auto类型推导规则根据类型修饰符也分三种情形,与模板类型推导完全一致,对数组参数和函数参数的处理也完全一致,不再赘述。

    开头说过,有一种情形auto与模板类型推导不一致。C++98初始化变量有两种方式:

    int x1 = 27;
    int x2(27);
    

    C++11增加了统一初始化语法:

    int x3 = { 27 };
    int x4{ 27 };
    

    这四种初始化方式效果都一样,把变量初始化为27。

    但是如果把变量类型改成auto:

    auto x1 = 27;
    auto x2(27);
    auto x3 = { 27 };
    auto x4{ 27 };
    

    此时,前两个变量的类型还是int。后面两个变量的类型变成了std::initializer_list<int>

    这是auto推导规则的一个特殊的地方,如果auto的变量初始化时使用了大括号,推导类型就是std::initializer_list。然而,模板推导时如果使用了大括号,则推导失败。

    auto x = { 11, 23, 9 }; // x类型是std::initializer_list<int>
    
    template<typename T>
    void f(T param);
    
    f({ 11, 23, 9 }); // 编译失败,无法推导出{ 11, 23, 9 }类型
    

    如果把模板参数改为如下形式,则可推导成功:

    template<typename T>
    void f(std::initializer_list<T> initList);
    
    f({ 11, 23, 9 }); // 编译通过,initList类型是std::initializer_list<int>,T是int型
    

    因此auto和模板类型推导的区别在于,auto会把大括号初始化推导为std::initializer_list,模板不会。

    最后,还有一点需要注意的地方,C++14允许指定函数返回值为auto,C++14的lambda表达式也允许参数类型为auto。这两种情况下的auto类型推导采用模板类型推导的规则。

    因此下面两段代码都编译不通过:

    auto createInitList() {
       return { 1, 2, 3 }; // 编译失败,无法推导{ 1, 2, 3 }类型
    }
    
    std::vector<int> v;
    
    auto resetV = [&v](const auto& newValue) { v = newValue; };
    
    resetV({ 1, 2, 3 }); // 编译失败,无法推导{ 1, 2, 3 }类型
    

    总结:

    • auto类型推导与模板类型推导基本一致,除了auto把大括号初始化推导为std::initializer_list,模板不会。
    • 函数返回值和lambda表达式参数中的auto采用模板类型推导的规则。

    相关文章

      网友评论

          本文标题:C++ auto 类型推导

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