C++ 进一步的右值引用和临时对象
在详细阐述我以前和现在的想法时,我想了解这个真实场景中发生了什么。我有以下模板功能:C++ 进一步的右值引用和临时对象,c++,c++11,undefined-behavior,move-semantics,rvalue-reference,C++,C++11,Undefined Behavior,Move Semantics,Rvalue Reference,在详细阐述我以前和现在的想法时,我想了解这个真实场景中发生了什么。我有以下模板功能: template <typename Key, typename Value, typename HashFunction, typename Equals> void FastHash<Key, Value, HashFunction, Equals>::Insert(const Key& key, const Value& value) { Insert(st
template <typename Key, typename Value, typename HashFunction, typename Equals>
void FastHash<Key, Value, HashFunction, Equals>::Insert(const Key& key, const Value& value)
{
Insert(std::make_pair(key, value));
}
(用于测试目的)<代码>插入以上调用
template <typename Key, typename Value, typename HashFunction, typename Equals>
void FastHash<Key, Value, HashFunction, Equals>::Insert(pair<const Key, Value>&& keyValuePair)
{
if (buckets.size() == 0)
{
buckets.resize(1);
}
HashFunction hash;
unsigned long hashValue = hash(keyValuePair.first) % buckets.size();
buckets[hashValue].push_back(std::move(keyValuePair));
}
模板
void FastHash::Insert(pair&&keyValuePair)
{
if(bucket.size()==0)
{
桶。调整大小(1);
}
散列函数散列;
无符号长hashValue=hash(keyValuePair.first)%bucket.size();
bucket[hashValue].push_-back(std::move(keyValuePair));
}
有几个问题:
1。由于通过引用传递,我希望将一对元素(其中一个元素是文本字符串)作为未定义的行为。是这样吗
2.当我进入make\u pair
行时,代码首先调用make\u pair(\u Ty1&&u Val1,\u Ty2&&u Val2)
,因此编译器似乎正在将键和值解释为右值。为什么?
3.进入第二个Insert
方法之前的下一个调用是pair(pair&&&u Right)
。无论第二次插入是采用&
还是采用常量&
,都会发生这种情况。这是怎么回事
4.与最后一个绑定,第二个插入的应该是常量对&
还是常量对&
更新:在观看Scott Meyer关于通用引用的精彩视频、阅读模板推导和引用折叠规则后,在您的帮助下,我可以回答1、2和4。但是我仍然无法理解为什么在调用Insert
之前调用对的移动构造函数。有什么帮助吗
进入第二个Insert方法之前的下一个调用是pair(pair&&&u Right)
。无论第二次插入是采用&&
还是常量&
,都会发生这种情况。这是怎么回事
这就是std::pair
的转换构造函数:它将传递的对从std::make\u pair(key,value)
转换为第二个Insert
函数的参数类型std::pair
。如果您自己指定对类型,而不是让std::make\u pair
推断它,则可以避免转换:
Insert(std::pair<const Key, Value>{key, value});
哈希表的类型是什么?快速哈希表。我想散列类型和相等类型并不重要。字符串文字具有静态存储持续时间。\u Ty1&&
是所谓的通用引用。在这种模式中,\u Ty&
,\u Ty1
可以被推断为左值引用(通过特殊规则,如果参数是左值)。如果推断它是对某些类型的左值引用
,则引用折叠适用,并且某些类型&&&
折叠为某些类型&
-该参数变为左值引用。就是这样!回答得好。我不明白的是:“在C++11中,我们有一条经验法则,如果你要复制某个东西,你应该根据它的值来接受它。”为什么?简而言之,当调用方传递左值时,按值接受将生成一个副本,当调用方传递右值时,将进入参数。这是两全其美。你应该读戴夫·亚伯拉罕的书
Insert(std::pair<const Key, Value>{key, value});
template <typename Key, typename Value, typename HashFunction, typename Equals>
void FastHash<Key, Value, HashFunction, Equals>::Insert(Key key, Value value)
{
Insert(std::pair<const Key, Value>{std::move(key), std::move(value)});
}