在详细阐述我之前的question和question时,我想了解这个真实场景中发生了什么。我有以下模板功能:
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));
}
例如,用pval和rvalues混合调用,就像在这个调用中一样:
std::string name = "The Great";
hashTable.Insert(name, "Gatsby");
(用于测试目的)。 Insert
以上的电话
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));
}
几个问题:
1。由于通过引用传递,我希望将其中一个元素的字符串作为未定义的行为。是这样吗?
2。当我进入make_pair
行时,代码首先调用make_pair(_Ty1&& _Val1, _Ty2&& _Val2)
,因此编译器似乎正在解释key
和{{ 1}}作为右值。为什么呢?
3。进入第二个value
方法之前的下一个电话是Insert
。无论第二个pair(pair<_Other1, _Other2>&& _Right)
是Insert
还是&&
,都会发生这种情况。这里发生了什么?
4。最后一次,如果第二个const &
选择Insert
或const pair&
,它会做什么?
更新:观看了Scott Meyer关于通用参考的精彩视频,阅读模板演绎和参考折叠规则,并在您的帮助下我可以回答1,2和4.但我仍然无法理解为什么在pair&&
调用之前调用pair
的移动构造函数。对此有何帮助?
答案 0 :(得分:1)
进入第二个Insert方法之前的下一个调用是
pair(pair<_Other1, _Other2>&& _Right)
。无论第二个插入内容是&&
还是const &
,都会发生这种情况。这是怎么回事?
这是std::pair
转换构造函数:它将您传递的对 - std::make_pair(key, value)
- 从std::pair<Key, Value>
转换为第二个Insert
函数的参数类型{{1} }。如果您自己指定对类型而不是std::pair<const Key, Value>
推导出它,则可以避免转换:
std::make_pair
当然,这是将参数复制到Insert(std::pair<const Key, Value>{key, value});
,而在C ++ 11中,我们有经验法则,如果要复制某些内容,则应按值接受它。因此,可以将此pair
实现为:
Insert