Effective Modern C++ Item2 理解auto类型推导

来源:互联网 发布:软件培训师收入 编辑:程序博客网 时间:2024/05/16 14:49

auto类型推导

在c++11之后, 我们可以通过auto关键字来定义一个变量,使我们可以免于显式地声明其类型,让编译器在编译时自动推导该变量的类型。如果你已经读过了 Effective Modern C++ Item1 模板类型推导详解 ,那么,除了一种特殊的情况外(初始化列表std::initializer_list),其实你已经知晓了关于auto类型推导的全部内容,因为auto类型推导实际上就是模板类型推导。
模板类型推导的形式如下:

//声明template<typename T>void f(ParamType param)//调用f(expr);

当进行auto类型推导时,有:

//  example1auto x = expr;//  example2auto& x = expr;//  example3auto&& x = expr;

在上述示例中,auto相当于模板中的T,不同的是ParamType:

  • example1中,ParamType为T,则x的类型推导规则遵循Item1中的Case3的情况。
  • example2中,ParamType为T&,则x的类型推导规则遵循Item1中Case1的情况。
  • exmaple3中,ParamType为T&&,则x的类型推导规则遵循Item1中Case2的情况。

auto类型推导实例:

#include <iostream>#include <memory>#include <vector>#include <typeinfo>int main(){    std::cout << std::boolalpha;    //auto的推导:    int x = 1;    auto y = x; //y的类型被推导为int,验证如下:    std::cout << "y的类型是int:" << std::is_same<decltype(y), int>::value << std::endl;    std::unique_ptr<int> ptr(new int{1});   //unique_ptr不允许拷贝构造(copy),只允许转移构造(move)    //auto ptr0 = uni_ptr;  //copy构造,编译不通过    auto uni_ptr = std::move(ptr); //move构造,成功运行,uni_ptr为右值引用,验证如下:    std::cout << "uni_ptr是右值引用:" << std::is_rvalue_reference<decltype(uni_ptr)>::value << std::endl;    //同时,uni_ptr是左值,因为该变量有名称/可以对其取地址,因此我们可以建立它的左值引用:    std::unique_ptr<int>& ptr_lr = uni_ptr; //ptr_lr为左值引用///////////////////////////////////////////////////////    //auto&的推导:    auto& ptr_a1 = uni_ptr;     //ptr_al 为左值引用,验证如下:    std::cout << "ptr_a1是左值引用:" << std::is_lvalue_reference<decltype(ptr_a1)>::value << std::endl;///////////////////////////////////////////////////////    //auto&&的推导:    auto&& ptr_a2 = uni_ptr;    //ptr_a2 也为左值引用,验证如下:    std::cout << "ptr_a2是左值引用:" << std::is_lvalue_reference<decltype(ptr_a2)>::value << std::endl;    std::vector< std::unique_ptr<char>> vec;    auto a = std::make_unique<char>('a');    auto b = std::make_unique<char>('b');    auto c = std::make_unique<char>('c');    vec.push_back(std::move(a));    vec.push_back(std::move(b));    vec.push_back(std::move(c));    //这里的elem被推导为左值引用    for (auto& elem : vec)        std::cout << *elem << " ";    puts("");    //这里的elem也被推导为左值引用    for (auto&& elem : vec)        std::cout << *elem << " ";    puts("");    system("pause");    return 0;}

总结:
从上面的实例可以看出
* 当我们把一个对象(obj)的类型声明为auto&时,我们只能使用一个左值对obj进行初始化,obj的类型一定为左值引用。
* 当我们把一个对象(obj)的类型声明为auto&&时:我们既可以使用左值对obj进行初始化,此时obj的类型为左值引用;也可以使用右值对obj进行初始化,此时obj的类型为右值引用。

0 0
原创粉丝点击