【问题标题】:Efficiency of output parameter vs return value on the stack for stl data structuresstl 数据结构的输出参数与堆栈上的返回值的效率
【发布时间】:2012-08-16 21:54:53
【问题描述】:

假设我有这些功能

std::Vector<Point> calculate() {
   std::Vector<Point> points; //do stuff with points
   return points;
}

void calculate(std::Vector<Point>& points) {
   //do stuff with points
}

所以我的问题是特定于在堆栈上初始化的对象,并且是 stl 对象。性能上有什么区别,流行的做法是什么

问候

【问题讨论】:

  • 取决于编译器优化和其他一些事情。
  • 你就不能试试这个基准,自己做一些推论吗?
  • @undu 当然可以,我想知道其他人更喜欢什么,并且仅仅因为一种方法在我的编译器和环境中产生了良好的结果并不能确定某种方法更好
  • @MoatazElmasry 不,请不要进行基准测试,至少在使用您(和其他回答者)的简单推理之前不要进行基准测试。

标签: c++ performance stl c++11


【解决方案1】:

由于复制省略,性能很可能是相同的。

两种方法表达的不同

std::vector<Point> calculate()

返回一个向量(可能基于某些参数)。

void calculate(std::vector<Point>& points)

修改现有向量(同样,可能基于参数)。

【讨论】:

  • 没有修改,可以说它只是一个输出参数而不是输入/输出
  • @MoatazElmasry 如果是输出,则返回值。这更符合 IMO 的逻辑。
  • @MoatazElmasry 这就是他回答的重点。引用参数建议输入/输出,因此具有与返回值不同的语义。
  • @MoatazElmasry 那么第二个选项将大大逊色。例如,如果输入向量不为空,您必须记录会发生什么,对其进行一些检查等等。
  • 除此之外,C++11 最终允许您依靠这种性能等效性作为保证(至少对于 std 容器和其他编写良好的轻量级包装器),并减轻您信任您的负担编译器的(可能是通常但仍由实现定义的)优化工具。
【解决方案2】:

取值作为参考参数有以下性质:

  1. 不会进行复制、移动或任何其他操作。
  2. 返回值不能在用户端立即丢弃。他们不能只是在你的函数的引用参数或其他东西上临时推一下。他们必须声明一个变量,因此他们必须给它一个名称,该名称将存在于当前范围内。
  3. API 建议该值是输入/输出参数。也就是说,有一个值被传入,将被读取和写入。如果不是这样,那么使用它就代表了一个次优的 API 设计元素。

返回值具有以下属性:

  1. 如果复制省略不可用(由于函数实现的性质、编译器性能不佳或返回值未初始化新值),则返回值将被移动。没有复制。移动不是免费的,但一般不会比几个指针副本贵多少。不会分配或释放新的对象或内存。
  2. API 强制值的输出性质。用户无法使用它传入的输出,因为它没有传入任何内容。同样,函数无法读取任何值,因为它不接受任何内容。它是一个输出价值,时期;该函数生成它并返回它。
  3. 可以根据用户的决定立即丢弃返回值。显然,如果用户经常这样做,则表明有问题,但要由用户决定是否要保留输出值。

【讨论】:

    【解决方案3】:

    我的拙见:返回值带来的问题多于解决的问题...它们看起来更简单,在调用部分更简洁,但会避免右值引用...

    缺点是表现力会降低,但这是一个很小的成本,因为像内存分配这样的资源会向上移动。

    C++ 必须而且可以在语法和资源管理方面得到显着简化。

    【讨论】:

    • 你能编辑你的答案更具体吗?返回值会带来什么问题?
    • 您好,欢迎来到 Stack Overflow。如果您详细说明为什么应该避免右值引用,这将提供更丰富的答案。
    猜你喜欢
    • 1970-01-01
    • 2012-12-24
    • 2021-05-29
    • 2022-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-07
    相关资源
    最近更新 更多