• C++11 类型推导auto


    在C++11之前,auto关键字用来指定存储期。在新标准中,它的功能变为类型推断。auto现在成了一个类型的占位符,通知编译器去根据初始化代码推断所声明变量的真实类型。
    使用auto会拖慢c++效率吗?完全不会,因为在编译阶段编译器已经帮程序员推导好了变量的类型。
    使用auto会拖累C++编译效率吗?完全不会,因为在auto出现之前C++需要先推导等号右侧表达式的类型,然后检查它与变量的类型是否可以转换(兼容转换、向下类型转换和自定义类型转换)。auto出现之后,C++在推导出等号右侧表达式的类型之后,直接指定给变量。


    auto并非一种类型声明,而是类型声明时的占位符,编译器在编译时期会将auto替代为变量的实际类型。因此不能和typeid,sizeof一起使用。

    1.使用auto通常意味着更短的代码(除非你所用类型是int,它会比auto少一个字母)

    试想一下当你遍历STL容器时需要声明的那些迭代器(iterator),现在不需要去声明那些typedef就可以得到简洁的代码了。

    std::map<std::string, std::vector<int>> map;
    for(auto it = begin(map); it != end(map); ++it) {}

    2.返回值占位符

    auto不能用来声明函数的返回值,但如果函数有一个尾随的返回类型时,auto是可以出现在函数声明中返回值位置。这种情况下,auto并不是告诉编译器去推断返回类型,而是指引编译器去函数的末端寻找返回值类型。在下面这个例子中,函数的返回值类型就是operator+操作符作用在T1、T2类型变量上的返回值类型。

    template <typename T1, typename T2>
    auto compose(T1 t1, T2 t2) -> decltype(t1 + t2)
    {
       return t1+t2;
    }
    auto v = compose(2, 3.14); // v's type is double

    3.auto声明的变量必须初始化

    int main()
    {
        auto m = 1; 
        auto n{1};
        auto z = new auto(10);
        
        auto a;                 //错误,未初始化
        auto int b = 1;         //错误,auto不能和其它类型一起使用(C++98和C中可以)
        auto c = new auto();    //错误,没有初始化
        auto d = 1, e = 2.01;   //错误,定义在一个auto序列的变量必须始终推导成同一类型
        
        return 0;
    }

    4.C++标准中规定auto可以与CV(const & volatile qualifiers)限制符一起使用,不过声明为auto的变量不能从其初始化表达式中带走CV限制符

    从const变量推导或用auto接收从函数返回的const变量,会丢失const属性,除非显示声明为引用类型。

    从引用变量推导或用auto接收从函数返回的引用变量,会丢失引用特性,除非显示声明为引用类型。

    #include <iostream>
    #include <typeinfo>
    #include <vector>
    
    using namespace std;
    
    struct student
    {
        std::string name;
        int age;
        student(std::string name, int age)
        : name(name)
        , age(age)
        {
            std::cout << "constructor" << std::endl;
        }
    
        student(const student& rhs)
        {
            std::cout << "copy constructor" << std::endl;
            this->name = rhs.name;
            this->age = rhs.age;
        }
    };
    
    student& backRef(student& s)
    {
        return s;
    }
    
    int main()
    {
        const auto var1 = 1;        //var1为const int
        auto var2 = var1;           //var1为int(除非var2声明为:auto& var2类型)
        auto& var3 = var1;          //var3为const int
        var2 = 3;                   //经过auto推导,var2变量已经丢失了const属性
        //var3 = 5;                 //错误,const变量禁止修改
    
        auto var4 = 4;
        auto& var5 = var4;          //var5是var4的引用类型
        var5 = 6;
        auto var6 = var5;           //从var5中推导,只会获得变量类型,会丢失引用特性
        var6 = 10;
        std::cout << "var4:" << var4 << std::endl;
        std::cout << "var5:" << var5 << std::endl;
        std::cout << "var6:" << var6 << std::endl;
    
        student stu1{"sanz", 10};
        auto stu2 = stu1;
    
        auto stu3 = backRef(stu1);  //函数返回引用类型,但实际会调用拷贝构造函数
        stu3.age = 12;
        auto& stu4 = backRef(stu1); //显示添加引用后,还是stu1
        stu4.age = 18;
        std::cout << stu1.age << std::endl;
        std::cout << stu2.age << std::endl;
        std::cout << stu3.age << std::endl;
        std::cout << stu4.age << std::endl;
    
        return 0;
    }
    View Code

    auto也不是万能的,受制于语法的二义性,或者是实现的困难性,auto往往也有使用上的限制。

    #include <iostream>
    #include <typeinfo>
    #include <vector>
    
    using namespace std;
    
    struct str
    {
        auto var = 10;      //1.a通过编译auto非静态成员变量,无法
    };
    
    void fun(auto x)        //2.auto函数参数,无法通过编译
    {
    }
    
    int main()
    {
        int x[3];
        auto y = x;
        auto z[3] = x;      //3.auto数组,无法通过编译
        
        //auto模版参数,无法通过编译
        vector<auto> v = {1};
        
        return 0;
    }

    分析一下上述4中不能推导的情况:

    1.对于函数fun来说,auto不能是其形参类型。由于其有默认参数,所以应该推导fun形参x的类型为int型。但事实无法符合大家的想象,如果程序员需要泛型的参数,还是求助与模版。

    2.对于结构体或类来说,非静态成员变量的类型不能为auto。编译器阻止auto对结构体中的非静态成员进行推导,即使成员拥有初始值。

    3.声明auto数组。x是一个数组,y类型是可以推导的,而声明auto z[3]这样的数字同样会被编译器禁止。

    4.在实例化模版的时候使用auto作为模版参数,虽然读者认为这里一眼而知是int类型,但编译器却阻止了编译。

  • 相关阅读:
    抓取猫眼电影top100的正则、bs4、pyquery、xpath实现方法
    Win实用好用软件清单推荐
    Manjaro安装配置美化字体模糊发虚解决记录
    爬取杭电oj所有题目
    Python爬取微博热搜以及链接
    20191225_Python构造函数知识以及相关注意事项
    java_细节_windows7下记事本保存为utf-8格式的问题
    基础_划分子网
    爬虫_爬取有道每日一句
    算法_基础_伪代码定义以及遵循的规则
  • 原文地址:https://www.cnblogs.com/DswCnblog/p/6520555.html
Copyright © 2020-2023  润新知