lang修改析构函数中的返回值? [英] Clang modifies return value in destructor?
问题描述
当试图编写一个类来调用构造函数和析构函数之间的持续时间时,我遇到了我认为是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是否无关
计时器
中的$ 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屋!