【问题标题】:Passing by Value and copy elision optimization按值传递和复制省略优化
【发布时间】:2013-09-20 10:15:12
【问题描述】:

我遇到了https://web.archive.org/web/20120707045924/cpp-next.com/archive/2009/08/want-speed-pass-by-value/

作者建议:

不要复制你的函数参数。相反,通过值传递它们 让编译器进行复制。

但是,我不太明白文章中介绍的两个示例有什么好处:

// Don't
T& T::operator=(T const& x) // x is a reference to the source
{ 
    T tmp(x);          // copy construction of tmp does the hard work
    swap(*this, tmp);  // trade our resources for tmp's
    return *this;      // our (old) resources get destroyed with tmp 
}

// DO
T& operator=(T x)    // x is a copy of the source; hard work already done
{
    swap(*this, x);  // trade our resources for x's
    return *this;    // our (old) resources get destroyed with x
}

在这两种情况下都会创建一个额外的变量,那么好处在哪里? 我看到的唯一好处是,如果将临时对象传递到第二个示例中。

【问题讨论】:

  • 如果源是临时的:obj = T();obj = foo(); 其中foo() 返回T
  • 这实际上不是很好的建议。它在接口中暴露了应该是实现细节(无论是否复制参数),这是非常糟糕的软件工程。有时分析器会说您必须这样做,但除此之外,您必须遵守编码指南。 (普遍的指导方针似乎是通过引用传递类类型,其他一切都通过值,尽管这也可能被视为过早的优化。)
  • @jameskanze “这个函数复制参数的状态”是一个合理的接口特性。除其他外,它会影响成本,它会告诉您必须实现参数类型的哪些功能,甚至会告知用户有关功能的信息。 C++11 的部分天才之处在于复制和移动很重要,并且对数据进行分区操作,并且将其暴露出来很重要。

标签: c++ compiler-optimization copy-elision


【解决方案1】:

关键在于,根据调用运算符的方式,可能会省略副本。假设您像这样使用您的运算符:

extern T f();
...
T value;
value = f();

如果参数由T const& 获取,编译器别无选择,只能保留临时变量并将引用传递给赋值运算符。另一方面,当您按值传递参数时,即它使用T,从f() 返回的值可以定位到该参数所在的位置,从而省略一个副本。如果赋值的参数是某种形式的左值,当然它总是需要复制。

【讨论】:

  • 关于异常也有区别。在T const& 的情况下,复制构造函数可以在被调用函数内抛出异常,但在T 的情况下,异常将在 caller 的上下文中抛出(这意味着即使复制构造函数可以抛出,赋值运算符也可以标记为noexcept
  • @Simple:实际上,这是一个有趣的观点!尽管最终它并没有太大的区别:整个表达式仍然可以抛出。结果,它可能使模板更容易使用条件noexcept
  • 第二种情况下的副本也可以用一个move来代替,即是从elision得到的区。
  • @DietmarKühl 感谢您的回复,很遗憾您的回答对我没有任何意义。所以,让我解释一下你的回复,看看它是否有意义(对你和其他读者)。这是我到目前为止得到的:我们有两个operator(s)= first,一个是常规类赋值运算符T::operator=(...),第二个是常规(函数)operator=(...)。按照您的代码,最终分配有两种可能性。
  • @DietmarKühl 第一种可能,value::operator=(f()),其中 rvalue temp 参数绑定到 const 左值引用参数(你可以这样做,因为它是 const),并且因为参数 x 在里面是左值(*如文章中所讨论的),无论如何都会复制到tmp,即不能省略复制。从角度来看:{temp_anon} 创建 - 一个副本,tmp - 第二个副本 - 2 个对象的内存被占用 + 2 个 ctor 调用 + 2 个 dtor 调用
猜你喜欢
  • 2021-10-29
  • 2015-07-14
相关资源
最近更新 更多