繁体   English   中英

左值到右值引用绑定

[英]Lvalue to rvalue reference binding

编译器一直抱怨我试图将左值绑定到右值引用,但我看不到如何。 我是 C++11 的新手,移动语义等,所以请耐心等待。

我有这个功能:

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.
}

调用此方法:

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

我不断收到如下错误:

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

在 Insert() 调用上。 key不是在运算符重载中定义为右值吗? 为什么它被重新解释为左值?

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

这里的keyKey&& key - 这是一个左值! 它有一个名字,你可以获取它的地址。 只是那个左值的类型是“对Key右值引用”。

您需要传入一个右值,为此您需要使用std::move

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

我明白为什么这是违反直觉的! 但是,一旦您区分了右值引用(即绑定到右值的引用)和实际右值,它就会变得更加清晰。

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

但是,在这种情况下,调用函数时不会推导出 Key 的类型,因为在实例化FastHash<std::string, ... >时它已经由类确定。 因此,您确实是在规定使用右值引用,因此使用std::move修复了代码。

我会将您的代码更改为参数按值获取:

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)
{
    // ...
}

不要太担心由于使用值参数而导致的额外副本 - 这些经常被编译器优化掉。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM