lang修改析构函数中的返回值? [英] Clang modifies return value in destructor?

查看:82
本文介绍了lang修改析构函数中的返回值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

While trying to write a class that times the duration between calling it's constructor and destructor, I ran into what I think is a bug in clang. ( it's not a bug; it's implementation defined copy elision)

下面的 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编译时,输出为:

When compiling this with clang 7.0.0, the output is:

some heavy calculation here
duration: 21642
function: 21642

而对于g ++ 8,输出是

while for g++ 8 the output is

some heavy calculation here
duration: 89747
function: 0

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

In this case I do like clangs behavior, but from what I've found elsewhere the return value is supposed to be copied before destructors are run.

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

Is this a bug with Clang? Or does this depend on (implementation defined?) return value optimization?

行为是否相同,与 duration d 计时器中的$ c>是指针或引用。

The behavior is the same independent of whether the duration d in timer is a pointer or a reference.

-

我确实意识到可以通过更改 f 来解决编译器不一致的问题,从而使计时器的作用范围在返回之前结束,但这不重要。

I do realise that the compiler inconsistency can be solved by changing f so that the scope of the timer ends before the return, but that's beside the point here.

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


推荐答案

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

Short answer: due to NRVO, the output of the program may be either 0 or the actual duration. Both are valid.

有关背景,请首先参见:

For background, see first:

  • in C++ which happens first, the copy of a return object or local object's destructors?
  • What are copy elision and return value optimization?

准则:


  • 避免使用破坏返回值的析构函数。

  • Avoid destructors that modify return values.

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

For example, when we see the following pattern:

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

我们需要问自己: A是否: 〜A()以某种方式修改我们的返回值?如果是,则我们的程序很可能存在错误。

We need to ask ourselves: does A::~A() modify our return value somehow? If yes, then our program most likely has a bug.

例如:


  • 打印破坏时的返回值的类型很好。

  • 计算破坏时的返回值的类型不是很好。

  • A type that prints the return value on destruction is fine.
  • A type that computes the return value on destruction is not fine.

这篇关于lang修改析构函数中的返回值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆