【发布时间】:2020-12-27 06:01:15
【问题描述】:
我正在阅读此 https://leanpub.com/cppmove (C++17 - The Complete Guide First Edition Nicolai M. Josuttisand) 并关于 c++17 结构化绑定和移动语义,它给出了以下示例,其中从对象 ms 移动保持原样:
MyStruct ms = { 42, "Jim" }; // struct has fields {int i, std::string s}
auto&& [v,n] = std::move(ms);
// author says: the structured bindings v and n refer to an anonymous
// entity being an rvalue reference to ms, while ms still holds its value:
std::cout << "ms.s: " << ms.s << '\n'; // prints "Jim"
我已经对此进行了测试,至少在实际运行中,这是正确的。但这通常也是它应该如何工作的吗?按照作者之前对结构化绑定的解释的方式,上面应该等同于
MyStruct ms = { 42, "Jim" };
auto&& e = std::move(ms); // anonymous compiler constructed entity "e"
/*aliasname*/ v = e.i; // v and n act as if e was constructed as
// above and v/n assigned to e.i/e.s as here
/*aliasname*/ n = e.s;
std::cout << "ms.s: " << ms.s << '\n'; // prints "Jim"
问题:
所以如果这是一个有效的解释,auto&& e = std::move(ms) 会不会导致ms 立即将其内容“移动”/“被盗”/“无效”?这样在“Jim”上面的两个(等效?)变体中都不会(保证)打印...?
澄清:我知道 std::move 不会移动任何东西,而是从左值转换为右值,但我认为这意味着至少你不能指望 std::move -ed 对象(此处为 ms)内容在后续使用中被保留/可用
标记为 What is std::move(), and when should it be used? 的骗子。然而,对于这个问题,有大约 300 人赞成,这个答案是:https://stackoverflow.com/a/27026280/11608725
首先要注意的是 std::move() 实际上并没有移动 任何事物。它将表达式从左值(例如 命名变量)成为一个xvalue。一个 xvalue 告诉编译器:
你可以掠夺我,移动我持有的任何东西并在其他地方使用 (反正我很快就会被毁掉)”。
换句话说,当您使用 std::move(x) 时,您允许 编译器蚕食 x
所以我想混乱是允许的:-P
请为超傻瓜推荐一本关于 c++17 和移动语义的好书——这本书的请求肯定是正确的;-)
【问题讨论】:
-
我认为您对
std::move有误解。实际上std::move既不移动也不构造任何东西。auto&& e = std::move(ms);中没有构造函数调用。 -
@churill,是的,但
move不应该等同于声明不能再指望ms 保留其原始内容,不是吗? -
std::move函数实际上并没有移动任何东西。 move 构造函数 可以,std::move允许您调用 move 构造函数。但在这种情况下,你没有这样做;auto&&提供参考。我很确定在这两个示例中,对std::move的调用没有任何用处。 -
std::move只是一个演员表。它将你给它的任何东西转换为一个 xvalue,这样你就可以从它移动,如果你把它给它会实际移动它的东西,比如移动构造函数。 -
@NathanOliver,是的,但这是否意味着后续使用
ms的合同?它的内容可能已被移动,所以不要指望它存在?
标签: c++ c++17 move-semantics structured-bindings