struct Base {
Base() {
std::cout << "Inside: " << __PRETTY_FUNCTION__ << std::endl;
}
~Base() {
std::cout << "Inside: " << __PRETTY_FUNCTION__ << std::endl;
}
};
struct BaseWrapper {
const Base &b;
};
int main()
{
{
auto *w = new BaseWrapper{{}};
std::cout << "Inside: " << __PRETTY_FUNCTION__ << std::endl;
delete w;
}
return 0;
}
当我用C ++ 11或C ++ 14编译时,上面的代码按预期工作,但是当我用C ++ 17编译时,它给了我类似的东西:
Inside: Base::Base()
Inside: int main()
如您所见,从未调用Base ::〜Base()。这对我来说没有多大意义。我已经在Ubuntu 18.04.1 LTS上的GCC 7.3.0和OnlineGDB上测试了此代码。它们都给出相同的结果。
我只是想知道这是C ++ 17中的新功能还是错误?
更新:
我很清楚w->b
是一个悬而未决的参考。实际上,我故意编写了这段代码只是为了说明这一点。然后,我在测试时发现了这个问题。
如果要坚持使用GCC 7.3,我真的想知道这个问题有多严重?还是有其他方法可以重现同一问题?或缺陷报告?
答案 0 :(得分:2)
很显然,创建但未被销毁的临时文件是编译器错误-除非标准说行为未定义。该示例定义良好。标准[class.temporary]中的相关规则:
当实现引入具有非平凡构造函数的类的临时对象([class.default.ctor],[class.copy.ctor])时,应确保为该临时对象调用构造函数。同样,析构函数应被调用为具有非平凡析构函数的临时变量([class.dtor])。临时对象被销毁是评估(按词法)包含创建点的完整表达式(intro.execution)的最后一步。 ...
在三种情况下,临时变量在与完整表达式结束时不同的位置被销毁。 ...
第三个上下文是将引用绑定到临时对象时...
此生存期规则的例外是:
...
绑定到新初始化器([expr.new])中引用的临时 持续存在,直到包含新初始化器的完整表达式完成。
答案 1 :(得分:0)
看起来像个错误,可能具有参考生存期延长和堆分配的对象。
有一些奇怪的生命周期扩展规则,其中包含引用成员的聚合初始化。
您可以升级编译器,也可以添加一个BaseWrapper(Base const& bin):b(bin){}
ctor并观察错误消失。