【发布时间】:2016-03-11 18:23:50
【问题描述】:
像这样的代码
#include <stdio.h>
struct P2d {
double x, y;
P2d(double x, double y) : x(x), y(y) {}
~P2d() { printf("Destructor called\n"); }
};
P2d center() {
return P2d(10, 10);
}
int main(int argc, const char *argv[]) {
const double& x = center().x;
printf("x = %.18g\n", x);
return 0;
}
g++ (版本 5.2.0) 将销毁P2d 临时实例在 进入main 中的printf,但无论如何都会保留该值(即代替绑定x 到临时 P2d 实例的实际成员,它将创建 另一个临时 double 以复制成员的值)。
clang++(IMO 正确)而是将临时 P2d 实例的生命周期延长到 x 引用的生命周期,因此析构函数将在 在printf 之后调用main.
如果不是使用普通的double 作为x 和y 成员的类型,而是创建一个类(例如Double),那么两个编译器都同意并将临时P2d 对象的生命周期延长到过去的printf。
这是g++ 中的错误还是标准允许的错误?
【问题讨论】:
-
在 2021 年 2 月 24 日在
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0上测试了这个程序,它打印了x = 10, Destructor called,所以必须“修复”。也会尝试 MSVC。 -
在同一天使用 msvc
Microsoft (R) C/C++ Optimizing Compiler Version 19.26.28805 for x64测试,即使使用/std:c++17,msvc 也会错误地打印Destructor called, x = 10
标签: c++ language-lawyer