std::make_pair(...)
和std::move(std::make_pair(...))
都是右值表达式(第一个是一个prvalue,第二个是一个xvalue)。由于emplace
需要转发参考,因此两者都被推断为相同类型,因此在这种情况下std::move
是多余的,但在一般情况下,冗余std::move
可以禁止复制省略。
m.emplace(1, std::make_pair(t1, t2));
相当于:
auto&& arg = std::make_pair(t1, t2);
std::pair<const int, std::pair<T, T>> e(1, std::forward<std::pair<T, T>>(arg));
执行地图元素的值的以下初始化:
auto&& arg = std::make_pair(t1, t2);
std::pair<T, T> p(std::forward<std::pair<T, T>>(arg));
注意,这是不同于:
std::pair<T, T> p(t1, t2);
形式r首先创建一个prvalue对(复制t1
和t2
),然后将其从(将复制的t1
和t2
移动到p
)移动。没有复制省略发生。
后者使用t1
和t2
来初始化存储在该对中的两个T
。
为了避免来自第一语法产生的不必要的移动,可以改为利用分段结构:
m.emplace(std::piecewise_construct
, std::forward_as_tuple(1)
, std::forward_as_tuple(t1, t2));
,这将是等同于:
auto&& arg = std::tuple<T&, T&>(t1, t2);
std::pair<T, T> p(std::get<0>(std::forward<std::tuple<T&, T&>>(arg))
, std::get<1>(std::forward<std::tuple<T&, T&>>(arg)));
,将初始化所述对的元素来自原始t1
和t2
的参考成员。
这里涉及到两个'std :: pair's。 –