c – 左值参考绑定的左值
作者:互联网
编译器一直在抱怨我试图将左值绑定到右值引用,但我看不出如何.我是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()调用上.是否将键定义为运算符重载中的右值?为什么它被重新解释为左值?
谢谢.
解决方法:
Insert(key, Value()); // Compiler error here
关键在于Key&&钥匙 – 这是一个左值!它有一个名字,你可以拿它的地址.只是该左值的类型是“对Key的rvalue引用”.
你需要传入一个右值,为此你需要使用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,...>时,类已经确定了它.因此,您确实使用了rvalue引用,因此使用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)
{
// ...
}
由于使用了值参数,不要过多担心额外的副本 – 这些通常由编译器优化.
标签:c,c11,rvalue-reference,move-semantics 来源: https://codeday.me/bug/20190930/1835519.html