在C中返回值优化和复制elision

有些人没有意识到可以按C中的值传递和返回结构 。 我的问题是关于在C中返回结构时编译器做不必要的拷贝。像GCC这样的C编译器使用返回值优化(RVO)优化还是C ++唯一的概念? 我所读到的关于RVO和copy elision的一切都是关于C ++的。

我们来看一个例子。 我目前正在C中实现一个double-double数据types (或者浮动浮动开始,因为我发现很容易unit testing)。 考虑下面的代码。

typedef struct { float hi; float lo; } doublefloat; doublefloat quick_two_sum(float a, float b) { float s = a + b; float e = b - (s - a); return (doublefloat){s, e}; } 

编译器是否会创build我返回的doublefloat值的临时副本,或者临时副本是否可以被删除?

那么C中的命名返回值优化(NRVO)呢? 我有另一个function

 doublefloat df64_add(doublefloat a, doublefloat b) { doublefloat s, t; s = two_sum(a.hi, b.hi); t = two_sum(a.lo, b.lo); s.lo += t.hi; s = quick_two_sum(s.hi, s.lo); s.lo += t.lo; s = quick_two_sum(s.hi, s.lo); return s; } 

在这种情况下,我返回一个命名的结构。 在这种情况下的临时副本是否可以被删除?

应该说这是C的一个普遍问题,我在这里使用的代码示例仅仅是示例(当我优化这个时,我将使用带有内在函数的SIMD)。 我知道,我可以看看汇编输出看看编译器做什么,但我认为这是一个有趣的问题。

RVO / NRVO在C中的“如果”规则下显然是允许的。

在C ++中,由于重载了构造函数,析构函数和/或赋值运算符以提供这些副作用(例如,在其中一个操作发生时将其打印出来),所以可以得到可观察的副作用,但是在C中,有能力重载这些操作符,而内置的操作符没有明显的副作用。

没有重载它们,你不会从副本中获得明显的副作用,因此没有什么能够阻止编译器这样做。

之所以为C ++覆盖很多,是因为在C ++中,RVO有副作用(即不调用临时对象的析构函数,也不调用结果对象的复制构造函数或赋值操作符)。

在C中,没有任何副作用,只有潜在的性能改进。 我没有看到这样的优化不能由一些编译器执行的理由。 至less,没有什么东西在标准中禁止它。

无论如何,优化是编译器和优化级别相关的,所以我不会在关键代码path上下注,除非编译器使用的定义良好,并且不会改变(通常情况下)。