17

我正在读这篇文章

我达到了以下代码。

我想知道:

  • 对字符串有用吗std::move(假设字符串足够长)?

  • 它会使先前的字符串无效吗?

  • 我应该在哪里使用它,在哪里不应该使用它?

.

class Name
{
public:
    Name(std::string firstName, std::string lastName)
      : firstName_(std::move(firstName))
      , lastName_(std::move(lastName)) {}

    void print() const
    {
        std::cout << lastName_ << ", " << firstName_ << '\n';
    }

private:
    std::string firstName_;
    std::string lastName_;
};

我的技术一直在使用

constructor(const std::string& argument): field(argument)
4

2 回答 2

12

当使用可移动类型的值时,按值接受参数的习惯用法是有意义的。消费一个值我的意思是这个值被转发到需要它自己的值副本的东西。这里的原因是这样的:

  • 当参数按值传递时,可以省略副本,例如,当参数是不同函数调用的结果时。即使无法省略副本,也可能使参数看起来像临时的(例如,使用std::move(arg))。
  • 由于一个值​​被传递给函数,即函数已经拥有一个副本,这个值可以转发到任何需要它的地方。
  • 在最坏的情况下,参数会被复制,但由于无论如何都需要一个值,因此也需要从T const&参数创建一个副本,并且假设额外的移动操作相对便宜。

因此,期望在最坏的情况下可能会有少量的额外工作,但在正常情况下,工作量会大大减少,因为只完成了一次移动操作而不是复制。

因为std::string它的参数比其他可移动类型稍微难一些,因为它非常常见的短字符串优化:可能需要传输字节而不是一些指针操作。然而,在实践中,复制短字符串或指针实际上只是memcpy()潜在地跟随指示移动操作的源不再包含需要释放的字符串的操作。

因此,简单的规则是

使用可移动对象时,按值接受参数并移动对象,而不是通过 a 传递参数T const&并创建副本以使用结果。

于 2017-12-16T01:37:36.400 回答
0

移动字符串时会消耗旧值:

  std::string sa = "Was the string";
  std::string sb = std::move(sa);
  std::cout << "Old [" << sa << "] new [" << sb << "]" << std::endl;

输出:Old [] new [Was the string]

我假设,旧值无需复制即可进入新字符串。当您需要在某些结构中分配字符串字段以作为参数传递时,这应该很有效,例如在ROS中:

  std::string my_message = method_that_returns_just_a_string();
  std_msgs::String message;
  message.data = std::move(my_message);

my_message 现在将包含一些“有效的未指定值”。示例输出包含空字符串,但您不应依赖它。

不会不必要地克隆 1Mb 的 XML。

于 2021-05-12T07:40:54.683 回答