条款24:区分万能引用和右值引用

考虑如下代码:

void f(Widget &&parm);		     // 右值引用

Widget &&var1 = Widget();	    // 右值引用

auto &&var2 = var1;				// 非右值引用

template<typename T>
void f(std::vector<T> &&param);	// 非右值引用

template<typename T>
void f(T &&param);				// 非右值引用

T&&有两种不同的含义:

  1. 其中一种含义为右值引用。
  2. 另外一种含义,则表示既可以是右值引用,亦可是左值引用。带有这种含义的引用在代码中形如右指值引用(T&&),称为万能引用;万能引用在以下两种情形出现:
template<typename T>
void f(T &&param);				// param是个万能引用
auto &&var2 = var1;				// var2是个万能引用

上述代码的共同之处,在于它们都涉及类型推导。paramvar2都是推导得到的;如果你看到了T&&,但是没有涉及类型的推导,那么,这就是一个右值引用,如:

void f(Widget &&parm);		     // 右值引用

Widget &&var1 = Widget();	    // 右值引用

因为万能引用首先是一个引用,所以必须进行初始化;万能引用的初始化物会决定它代表是个左值引用还是右值引用:

template<typename T>
void f(T &&param);		// param为万能引用

Widget w;
f(w);				   // 左值被传递给f,param的类型是Widget&,左值引用

f(std::move(w));	  // 右值被传递给f,param的类型是Widget&&,右值引用

若要使得一个引用称为万能引用,其涉及到类型推导是必要条件,而不是充分条件:

template<typename T>
void f(std::vector<T> && param);  // param是个右值引用

f被调用时,类型T將被推导,但是param的类型声明形式不是T&&,而是std::vector<T>&&;这个事实在你试图传递左值给f时编译器很乐意为你确认出来:

std::vector<int> v;
f(v);	// 错误!不能给右值绑定一个左值

如果你在一个模板内看到一个函数形参写作T&&,你可能会想当然认为它肯定是个万能引用。不能想当然,如下:

template<class T, class Allocator = allocator<T>>
class vector {
public:
	void push_back(T&& x);
};

push_back不涉及类型推导,因为push_back作为vector的一部分,如果不存在特定的vector实例,则它也无从存在。该实例的类型完全决定了push_back的声明类型,即:std::vector<Widget> v会导致std::vector模板具现化为如下实例:

template<class T, class Allocator = allocator<T>>
class vector {
public:
	void push_back(Widget&& x); //右值引用
};

作为对比,emplace_back却实实在在的涉及类型推导:

template<class T, class Allocator = allocator<T>>
class vector {
public:
	template<class... Args>
	void emplace_back(Args&&... args);
};

其中的类型形参Args独立于vector的类型形参T,所以,Args必须在每次emplace_back被调用时进行推导 。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值