c – 通过`\u0026\u0026`传递的参数对非构造函数有用吗?

一个可能有一个函数void setData(std :: string arg);并通过setData(std :: move(data))调用它;因此调用move构造函数,他会对void setData(std :: string&& arg)做同样的事情. (除非他被迫将数据移入其中).如果对简单情况应该使用move,那么编译器决定做什么呢?

所以我的问题是:一个人应该使用&&不仅是编译器,还有一般代码(例如为其他开发人员创建的API成员)?

解决方法

优化r值

比较void setData(std :: string arg)和void setData(std :: string&& arg).在第一种情况下,我假设setData将数据移动到位

class Widget {
  std::string data;
 public:
  void setData(std::string data) { this->data = std::move(data); }
};

如果我们这样称呼它

w.setData(std::move(data));

我们将调用move构造函数来构造函数参数,并调用move赋值运算符将数据移动到成员变量中.所以总共有两个动作.

但是如果我们像这样重载r值引用:

class Widget {
  std::string data;
 public:
  void setData(std::string&& data) { this->data = std::move(data); }
};

您只能调用一次移动赋值运算符.你可能会说“但行动很便宜!”这可能是真的.在某些情况下,它们并不便宜(例如std :: array),在std :: string的情况下,大多数编译器实现了小字符串优化(SSO),因此对于小字符串,移动并不比副本便宜.

优化l值

pass-by-value的参数通常是你可以优化l值和r值而不必提供两个重载void setData(const std :: string& arg)和void setData(std :: string&& ; arg).因此,让我们比较一下如果我们将l值传递给void setData(std :: string arg)vs void setData(const std :: string& arg)会发生什么.在第一种情况下,您将获得一个无条件副本,然后一个移动分配.在第二种情况下,您只需获得一项任务.额外的移动分配可能是微不足道的,但无条件副本可能比分配要昂贵得多.如果在同一对象上多次调用setData,则分配可能能够重新使用现有容量并避免重新分配.无条件副本将始终必须进行分配.

可能这些考虑在实践中是微不足道的,但值得了解它们.

记录/实施所有权转移

r值参考参数的另一个用途是记录/强制执行所有权转移.假设您有一些可复制和可移动的大对象,那么您可能只提供void setData(BigData&& data)来强制执行移动.除了使某人不小心制作副本的可能性降低之外,它还记录了我们对数据的所有权.您不一定需要移动整个对象,您可能只是窃取对象的一部分.

相关文章

文章浏览阅读315次。之前用C语言编过链表,这几天突然想用C+...
文章浏览阅读219次。碰到问题就要记录下来,防止遗忘吧。文章...
文章浏览阅读1.8k次,点赞11次,收藏37次。因为自己对决策树...
文章浏览阅读492次。C++ 设计模式之策略模式
文章浏览阅读683次。我也算是个C++的小白,对于C++中的谓语我...
文章浏览阅读225次。又看了一遍操作符的东西,感觉之前对操作...