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)});
}