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

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

我们来看一个例子。 我目前正在C中实现一个double-double数据类型(或者说float float,因为我发现它很容易进行单元测试)。 考虑下面的代码。

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};
}

编译器是否会创建我返回的doublefloat值的临时副本,或者是否可以暂时复制临时副本?

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

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和intrinsics无论如何)。 我知道我可以查看汇编输出以查看编译器的功能,但我认为这是一个有趣的问题。


RVO / NRVO在C中的“as-if”规则下显然是允许的。

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

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


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

在C中,没有可能的副作用,只有潜在的性能改进。 我看不出有些编译器无法执行这样的优化。 至少,没有什么东西在标准中禁止它。

无论如何,优化是编译器和优化级别相关的,所以我不会为关键代码路径下注,除非使用的编译器定义良好,并且不会发生变化(通常情况下仍然如此)。

链接地址: http://www.djcxy.com/p/72913.html

上一篇: Return value optimization and copy elision in C

下一篇: copy elision method