绑定到已销毁堆栈变量的 const 引用的生命周期

Lifetime of const references bound to destroyed stack variable

我想知道它是否偶然指向绑定到已销毁堆栈变量的 const 引用的指针可以正常工作。
我读到 const 引用生命周期在 上延长,所以这是 "normal" const 引用有效但在存储引用的 ctor 结束时应该被销毁,不是吗?
const 引用的生命周期是否也延长了,因为我在指针中检索了它的地址,还是这纯粹是运气?

Live example

#include <iostream>

class Storage
{
public:
    Storage(const int& ref)
    {
        p = &ref;
    }

    const int* Get() const
    {
        return p;
    }

private:    
    const int* p;
};

int main()
{
    Storage* s = nullptr;

    {
        int someValue = 42;
        std::cout << &someValue << std::endl;
        s = new Storage(someValue);
    }

    const int* p = s->Get();
    std::cout << p << std::endl;
    std::cout << *p << std::endl;
}

它也在使用结构 Live example

#include <iostream>

struct Dummy
{   
    int value;
};

class Storage
{
public:
    Storage(const Dummy& ref)
    {
        p = &ref; // Get address of const reference
    }

    const Dummy* Get() const
    {
        return p;
    }

private:    
    const Dummy* p;
};

int main()
{
    Storage* s = nullptr;

    {
        Dummy dummy;
        dummy.value = 42;
        std::cout << &dummy << std::endl;
        s = new Storage(dummy);
    }

    const Dummy* p = s->Get();
    std::cout << p << std::endl;
    std::cout << p->value << std::endl;
}

您的 s 变量确实有一个悬空指针,因为 someValue 已超出范围。因此,您的代码表现出未定义的行为。

您关于 "const reference lifetime is extended on rvalues" 的评论在某些情况下是正确的,但 someValue 是一个 lvalue

编译器可能会在一开始就为所有局部变量分配堆栈 space,因此即使超出范围,someValue 仍位于内存中的同一位置。当然,不同的编译器可能会做一些不同的事情,并且它可能会被后续的局部变量覆盖。

对于你的第二个例子,如果你写了一个 ~Dummy(){ value=0; },那就不行了,证明dummy object的生命周期没有被延长