【问题标题】:Is it better to pass-by-value and then move-construct or to pass-by-reference and then copy-construct [duplicate]是通过值传递然后移动构造还是通过引用传递然后复制构造更好[重复]
【发布时间】:2014-05-28 11:55:29
【问题描述】:

在 C++11 中的构造函数中,这样做更好吗:

class A
{
  A(std::string str) : mStr(std::move(str)) {}
  std::string mStr;  
}

或去做

class A
{
  A(const std::string& str) : mStr(str) {}
  std::string mStr;  
}

在将右值传递给构造函数时,在哪些情况下会发生复制省略?

【问题讨论】:

  • 如果传入的参数不再被检查,一个足够聪明的编译器可以忽略所有这些。这与以往的规则相同:as-if 规则。如果你的代码不能区分,编译器可以做到。
  • @R.MartinhoFernandes:这里我不太确定,std::string 的复制构造函数有副作用(内存分配),只允许复制省略忽略在一个非常狭窄的情况(我相信只包括从函数返回)。
  • @MatthieuM。除非您覆盖 new,否则这些副作用是不可观察的。 as-if 规则取代了复制省略规则,因为 as-if 规则允许一切。
  • Want speed? Pass by value. 当然,这不是一个通用规则,但它确实回答了您的问题 - 支持按值传递 + 移动。
  • @MatthieuM。 C++14 使内存分配可优化。具体来说 - 来自N3936 - 5.3.4/8 “新表达式可能通过调用分配函数 (3.7.4.1) 来获取对象的存储空间。”和 5.3.4/10 “允许实现省略对可替换全局分配函数(18.6.1.1、18.6.1.2)的调用。”

标签: c++ c++11


【解决方案1】:

如果你的类型的移动构造函数很便宜,你应该使用“传递值然后移动构造”,否则使用“传递引用然后复制构造”。

对于左值

按值传递,然后移动构造

您将先复制一份,然后再进行一次移动。

通过引用传递然后复制构造

你只做一份

对于右值

按值传递,然后移动构造

在最好的情况下(当右值是一个临时表达式时)您将不进行复制/不移动,然后进行移动。

在正常情况下(当右值不是临时表达式时),您将进行一次移动,然后进行另一次移动。

通过引用传递然后复制构造

你只做一份

【讨论】:

  • 按值传递然后移动的另一个优点是能够在函数调用之前触发可能的抛出代码并向其添加 noexcept 限定符。
  • 应该提到完美转发(手动或魔术)
  • @yakk 哦,请继续。我不想写一个大的答案。
猜你喜欢
  • 2011-05-06
  • 1970-01-01
  • 2012-07-05
  • 2020-04-01
  • 2016-06-11
  • 2014-01-29
  • 1970-01-01
  • 1970-01-01
  • 2012-03-19
相关资源
最近更新 更多