【问题标题】:Why is std::move( arg ) altering arg argument?为什么 std::move( arg ) 改变 arg 参数?
【发布时间】:2018-04-17 07:03:38
【问题描述】:

有代码

string one = "one";
string two{ one };
string three{ move(one)};
cout << one  << endl;

这会打印“”。这是因为调用了字符串 3 的移动构造函数并窃取了它的参数值。但是,变量一是怎么修改的呢?

当我们通过move(one) 时返回右值。并且移动构造函数从那个右值窃取资源,变量一没有作为引用或指针传递在那里。那么这种行为是怎么发生的呢?

感谢回答

【问题讨论】:

  • move(one) 给你一个右值reference
  • “变量 one 没有作为引用或指针传递。” - 是的。 std::move() 不会创建一个临时的它执行类型转换。所以右值是one 从左值转换为右值引用
  • 构造函数如何知道你保留了一个引用?您使用 move(one) 明确指定将所有权传递给构造函数,因此该行为是合法的
  • 明确地说,std::move(arg) 只是一个演员表。改变参数的是std::string 的构造函数。这正是std::move 的用途——避免复制字符串数据。

标签: c++ c++11 move-semantics


【解决方案1】:

std::move() 实际上并没有改变它的论点

...但它确实让代码采用它的输出“蚕食”了参数。因此,您的three 字符串会占用one 的缓冲区,使其为空。

您也可以在网站上阅读this detailed explanation 关于std::move()(回答问题"what is std::move() and when should it be used")。

【讨论】:

    【解决方案2】:

    在标题中,你问:

    为什么std::move( arg ) 改变arg 参数?

    std::move(arg) 不会改变arg 的内容。它只是将arg 转换为右值引用。

    调用std::string的构造函数
    string three{ move(one)};
    

    更改one 的内容,因为它调用了“move”构造函数。

    这是期望的行为。您要求编译器将数据从one“移动”到three。目的是蚕食one 的内容并使其处于empty 状态。当然,empty 的概念是特定于编译器的。

    您可以在http://www.stroustrup.com/C++11FAQ.html#rval 阅读有关右值引用、移动构造函数和移动赋值运算符的更多信息。

    回复:

    当我们通过 move(one) 时,返回右值。

    这是不正确的。 move(one) 返回一个右值引用。

    【讨论】:

      【解决方案3】:

      当我们通过move(one) 时返回右值。并且 move 构造函数从 THAT rvalue 窃取资源,变量 one 没有作为引用或指针传递。

      “THAT rvalue”是one 对象。所以three 窃取了one 的数据。

      在这一行:

      string three{move(one)};
      

      three 接收到one 的右值引用,因此当它从该右值引用中窃取数据时,它会从one 中窃取数据,因为右值引用@987654329 @对象。

      由于one 有一个名字并且你可以获取它的地址,它不是一个右值引用。使用std::move()cast 到一个右值引用,这样你就可以从它移动。在您离开它之后,它的状态是未指定。对于std::string,这意味着您从它移开后无法知道它包含什么。它可以包含任何东西。移动后它仍然是有效的std::string,但其内容未知。在您的特定编译器/库中,新状态恰好是一个空字符串。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-16
        • 2022-06-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多