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

auto类型推导

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

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

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

//  example1
auto x = expr;
//  example2
auto& x = expr;
//  example3
auto&& 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的类型为右值引用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值