Ale*_*ato 7 c++ move-semantics c++11
#include <iostream>
#include <string>
#include <map>
struct A {
int n { 42 };
std::string s { "ciao" };
};
int main() {
A a;
std::map<std::string, A> m;
std::cout << "a.s: " << a.s << std::endl; // print: "a.s: ciao"
m.emplace(a.s, std::move(a)); // a.s is a member of a, moved in the same line
std::cout << "in map: " << m.count("ciao") << std::endl; // print: "in map: 1"
std::cout << "a.s: " << a.s << std::endl; // print: "a.s: " (as expected, it has been moved)
}
Run Code Online (Sandbox Code Playgroud)
作为参数传递"移动"对象的成员是否安全?在这种情况下,emplace似乎有效:地图具有预期的关键.
有趣的。我认为这是安全的,原因很复杂。(郑重声明,我也认为这种风格非常糟糕——明确的副本在这里不需要花费任何费用,因为它将被移动到地图中。)
首先,实际的函数调用是没有问题的。std::move仅转换a为右值引用,而右值引用只是引用;a 没有立即移动。emplace_back将其参数转发给 的构造函数std::pair<std::string, A>,这就是事情变得有趣的地方。
std::pair那么,使用了哪个构造函数呢?它有很多,但有两个是相关的:
pair(const T1& x, const T2& y);
template<class U, class V> pair(U&& x, U&&y);
Run Code Online (Sandbox Code Playgroud)
(参见标准中的 20.3.2),其中T1和T2是 的模板参数std::pair。根据 13.3,我们最终得到后者的U == const T1&和V == T2,这具有直观意义(否则进入 astd::pair实际上是不可能的)。这给我们留下了以下形式的构造函数
pair(const T1& x, T2 &&y) : first(std::forward(x)), second(std::forward(y)) { }
Run Code Online (Sandbox Code Playgroud)
按照 20.3.2 (6-8)。
那么,这安全吗?有用的是,std::pair定义了一些细节,包括内存布局。它特别指出
T1 first;
T2 second;
Run Code Online (Sandbox Code Playgroud)
按照这个顺序来,所以first会在 之前初始化second。这意味着在您的特定情况下,字符串将在移走之前被复制,并且您是安全的。
但是,如果您以相反的方式这样做:
m.emplace(std::move(A.s), A); // huh?
Run Code Online (Sandbox Code Playgroud)
...然后你会得到有趣的效果。
| 归档时间: |
|
| 查看次数: |
226 次 |
| 最近记录: |