Clang 修改析构函数中的返回值?

2023-11-26

在尝试编写一个类来计算调用其构造函数和析构函数之间的持续时间时,我遇到了我认为是 clang 中的错误。 (编辑:这不是一个错误;它是实现定义的复制省略)

The timer下面的结构体保留一个指向作为引用传入的持续时间对象的指针,并将范围的持续时间添加到其中。

#include <iostream>
#include <chrono>
struct timer {
    using clock      = std::chrono::high_resolution_clock;
    using time_point = clock::time_point;
    using duration   = clock::duration;
    duration* d_;
    time_point start_;
    timer(duration &d) : d_(&d), start_(clock::now()) {}
    ~timer(){
        auto duration = clock::now() - start_;
        *d_ += duration;
        std::cerr << "duration: " << duration.count() << std::endl;
    }
};

timer::duration f(){
    timer::duration d{};
    timer _(d);
    std::cerr << "some heavy calculation here" << std::endl;
    return d;
}

int main(){
    std::cout << "function: " << f().count() << std::endl;
}

使用 clang 7.0.0 编译此文件时,输出为:

some heavy calculation here
duration: 21642
function: 21642

而对于 g++ 8 输出是

some heavy calculation here
duration: 89747
function: 0

在这种情况下,我确实喜欢 clang 行为,但从我在其他地方发现的情况来看,返回值应该在析构函数运行之前被复制。

这是 Clang 的错误吗?或者这取决于(实现定义的?)返回值优化?

无论是否duration d in timer是指针或引用。

--

我确实意识到编译器不一致可以通过改变来解决f这样计时器的范围在返回之前就结束了,但这不是这里的重点。

timer::duration f(){
    timer::duration d{};
    {
        timer _(d);
        std::cerr << "some heavy calculation here" << std::endl;
    }
    return d;
}

简短回答:由于 NRVO,程序的输出可能是0或实际持续时间。两者都有效。


有关背景,请先参阅:

  • 在 C++ 中,返回对象的副本或本地对象的析构函数首先发生?
  • 什么是复制省略和返回值优化?

指导方针:

  • 避免修改返回值的析构函数。

例如,当我们看到以下模式时:

T f() {
    T ret;
    A a(ret);   // or similar
    return ret;
}

我们需要问自己:A::~A()以某种方式修改我们的返回值?如果是,那么我们的程序很可能有错误。

例如:

  • 在销毁时打印返回值的类型就可以了。
  • 计算销毁返回值的类型是not fine.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Clang 修改析构函数中的返回值? 的相关文章

随机推荐