Lvalue到右值引用绑定 [英] Lvalue to rvalue reference binding

查看:113
本文介绍了Lvalue到右值引用绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编译器不断抱怨我试图绑定一个左值到右值引用,但我看不到如何。我是新来的C ++ 11,移动语义等,所以请与我一起。



我有这个功能:

  template< typename Key,typename Value,typename HashFunction,typename Equals> 
Value& FastHash< Key,Value,HashFunction,Equals> :: operator [](Key& amp; key)
{
//这里有些代码...

,Value()); //编译器错误这里

//这里有更多的代码。
}

调用此方法:

  template< typename Key,typename Value,typename HashFunction,typename Equals> 
void FastHash< Key,Value,HashFunction,Equals> :: Insert(key&&&&&&&& amp; value)
{
// ...
}

我会收到如下错误:

 无法将参数1从std :: string转换为std :: string&&'

。在操作符重载中,是否定义为右值?为什么会被重新解释为小值?



谢谢。

解决方案

 插入(键,值()); //编译器错误在这里

key这里是Key&&左价!它有一个名称,你可以取它的地址。它只是那个左值的类型是右值引用Key。



你需要传入一个右值,因此你需要使用std :: move:

 插入(std :: move(key),Value()); //没有编译器错误任何更多

我可以看到为什么这是反直觉!但是一旦你区分和右值引用(这是一个绑定到右值的引用)和一个实际右值,它变得更清楚。



编辑:这里真正的问题是使用rvalue引用。在推导参数类型的函数模板中使用它们是有意义的,因为由于参考折叠规则,这允许参数绑定到左值引用或右值引用。请参阅这篇文章和视频了解原因: http:// isocpp .org / blog / 2012/11 / universal-references-in-c11-scott-meyers



但是,在这种情况下,在调用函数时推导出来,因为它已经由类实例化FastHash时确定。因此,你真的在​​处方使用右值引用,因此使用 std :: move 修复代码。



我将更改你的代码,参数取值为:

  template< typename Key,typename Value,typename HashFunction typename等于> 
Value& FastHash< Key,Value,HashFunction,Equals> :: operator [](Key key)
{
//这里有些代码...

Insert (key),Value());

//这里有更多的代码。
}

template< typename Key,typename值,typename HashFunction,typename Equals>
void FastHash< Key,Value,HashFunction,Equals> :: Insert(Key key,Value value)
{
// ...
}

不要担心由于使用值参数而产生的额外副本 - 这些常常由编译器优化。 p>

The compiler keeps complaining I'm trying to bind an lvalue to an rvalue reference, but I cannot see how. I'm new to C++11, move semantics, etc., so please bear with me.

I have this function:

template <typename Key, typename Value, typename HashFunction, typename Equals>
Value& FastHash<Key, Value, HashFunction, Equals>::operator[](Key&& key)
{
    //  Some code here...

    Insert(key, Value()); // Compiler error here

    //   More code here.
}

which calls this method:

template <typename Key, typename Value, typename HashFunction, typename Equals>
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key&& key, Value&& value)
{
    // ...
}

I keep getting errors like the following:

cannot convert argument 1 from 'std::string' to 'std::string &&'

on the Insert() call. Isn't key defined as an rvalue in the operator overload? Why is it being reinterpreted as an lvalue?

Thanks.

解决方案

Insert(key, Value()); // Compiler error here

"key" here is "Key&& key" - this is an lvalue! It has a name, and you can take its address. It's just that type of that lvalue is "rvalue reference to Key".

You need to pass in an rvalue, and for that you need to use std::move:

Insert(std::move(key), Value()); // No compiler error any more

I can see why this is counter-intuitive! But once you distinguish between and rvalue reference (which is a reference bound to an rvalue) and an actual rvalue, it becomes clearer.

Edit: the real problem here is using rvalue references at all. It makes sense to use them in a function template where the type of the argument is deduced, because this allows the argument to bind to either an lvalue reference or an rvalue reference, due to reference collapsing rules. See this article and video for why: http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

However, in this case the type of Key is not deduced when the function is called, as it has already been determined by the class when you instantiated FastHash. Thus you really are prescribing the use of rvalue references, and thus using std::move fixes the code.

I would change your code to that the parameters are take by value:

template <typename Key, typename Value, typename HashFunction, typename Equals>
Value& FastHash<Key, Value, HashFunction, Equals>::operator[](Key key)
{
    //  Some code here...

    Insert(std::move(key), Value());

    //   More code here.
}

template <typename Key, typename Value, typename HashFunction, typename Equals>
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key key, Value value)
{
    // ...
}

Don#t worry too much about extra copies due to use of value arguments - these are frequently optimised out by the compiler.

这篇关于Lvalue到右值引用绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆