c++ - std::move 与 std::make_pair

标签 c++ c++11 dictionary move

有什么区别:

std::map <int,std::pair<T,T>> m;
T t1,t2;
m.emplace(1,std::make_pair(t1,t2));

和:

std::map <int,std::pair<T,T>> m;
T t1,t2;
m.emplace(1,std::move(std::make_pair(t1,t2)));

std::move 在这里是多余的吗? std::map::emplaceperfect forwarding 是否负责直接在std::中分配std::pair map ?

最佳答案

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

它执行 map 元素值的以下初始化:

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

前者首先创建一个 prvalue 对(复制 t1t2),然后从中 move ( move 复制的 t1 > 和 t2p)。不会发生复制省略。

后者使用 t1t2 来初始化存储在对中的两个 T

为了避免第一种语法导致的不必要的 move ,您可以改用分段构造:

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

这将从绑定(bind)到原始 t1t2 的引用成员初始化对的元素。

关于c++ - std::move 与 std::make_pair,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36906575/

相关文章:

c# - 如何在 C++ 和 C# 之间传递带有空字符的字符串?

c++ - 在声明中合并两个常量 `std::set`(不是在运行时)

c++ - C++中嵌套函数声明的范围

c++ - std::vector 构造,具有元素的就地构造

c++ - 将 std::find_if() 与采用多个输入参数的比较函数一起使用

c++ - 优化修剪功能

java - ConcurrentHashMap 和 Collections.synchronizedMap(Map) 有什么区别?

python - 如果列表中存在值,则返回键(来自字典)

dictionary - Racket 映射笛卡尔积事物

c++ - boost::future::then() 不返回阻止销毁的 future