std::move 和 std::make_pair
std::move with std::make_pair
有什么区别吗:
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::emplace
和 perfect forwarding
会直接在 std::map
中分配 std::pair
吗?
m.emplace(std::make_pair(1, std::make_pair(t1,t2)));
将调用移动构造函数。
std::make_pair(...)
和 std::move(std::make_pair(...))
都是右值表达式(第一个是纯右值,第二个是亡值)。由于 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);
前者首先创建一个纯右值对(复制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::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::emplace
和 perfect forwarding
会直接在 std::map
中分配 std::pair
吗?
m.emplace(std::make_pair(1, std::make_pair(t1,t2)));
将调用移动构造函数。
std::make_pair(...)
和 std::move(std::make_pair(...))
都是右值表达式(第一个是纯右值,第二个是亡值)。由于 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);
前者首先创建一个纯右值对(复制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
.