WeHack BBS
C++对象的生命周期问题 - 可打印的版本

+- WeHack BBS (https://bbs.wehack.space)
+-- 版块: 计算机技术 (https://bbs.wehack.space/forum-5.html)
+--- 版块: 程序设计讨论区 (https://bbs.wehack.space/forum-14.html)
+--- 主题: C++对象的生命周期问题 (/thread-327.html)



C++对象的生命周期问题 - vimacs - 12-30-2021

代码:
class A
{
    int *p_int;

    public:
    A(int *p): p_int(p){}
    const A &add() const { (*p_int)++; return *this; }

    int val() const { return *p_int; }
};

inline A construct(int *x)
{
    return A(x);
}

int main()
{
    int v = 42;
#ifdef ADD
    // ASAN will complain
    auto &obj = construct(&v).add();
#else
    // ASAN does not complain
    const auto &obj = construct(&v);
    obj.add();
#endif

    return obj.val();
}

这段代码中 #ifdef 到 #endif 之间的两段代码区别是什么?

开始我没想明白,到 #gcc 问了一下,得到的答案也看不懂,于是我尝试着自己看 Clang AST 了解这两段代码的语义。搞明白下面这几点,就知道答案了。

1. clang++ -Xclang -ast-dump -fsyntax-only test.cc 可以查看 test.cc 的 AST. 里面有一个节点叫 MaterializeTemporaryExpr.
2. 看 Clang 的源码,clang/include/clang/AST/ExprCXX.h 有 MaterializeTemporaryExpr 注释中写着引用绑定可以延长临时值的生命周期。

里面举了个例子: ``const int &r = 1.0;`` 这个语句中,将浮点数 1.0 转为整数产生了一个临时值,通过引用绑定后,这个临时值的生命周期得到延长,不会被丢弃。

于是上面第一段代码出问题的原因,实际上是 ``construct(&v)`` 在语句执行结束之后就被丢弃,临时对象被析构,导致后续尝试使用时出错。


RE: C++对象的生命周期问题 - shangyatsen - 12-31-2021

确实,常量引用能延长纯右值的生命周期,好像是这样的。。