0

可能重复:
可以在其范围之外访问局部变量的内存吗?
C ++构造函数:初始化常量引用时产生垃圾

这个问题与我之前问过的另一个问题直接相关:“不透明的引用而不是 PImpl。这可能吗?” .

假设我们有一个类,它的引用成员是其他类的成员,该成员在构造函数中初始化为临时变量:

#include <iostream>

struct B
{
    B(int new_x = 10) : x(new_x) { std::cout << "B constructed\n"; }
    ~B() { std::cout << "B destroyed\n"; }

public:
    int x;
};

struct A
{
    A()
    : b( B(23) )
    {
        std::cout << "A constructed\n";
    }

    void Foo()
    {
        std::cout << "A::Foo()\n";
    }

    ~A()
    {
        std::cout << "A destroyed\n";
    }

public:
    const B& b;
};

int main()
{
    A a;
    a.Foo();
    cout << "x = " << a.b.x << endl;
}

当我运行上面的代码时,输​​出是:

B constructed
B destroyed
A constructed
A::Foo()
x = 23
A destroyed

似乎即使临时被破坏所以引用成员应该是无效的,引用成员的整数字段仍然是可读的。为什么它仍然有效?

4

3 回答 3

1

未定义的行为。在您的情况下,临时占用的内存B在您引用它之前不会被覆盖。下次运行程序时,任何事情都可能发生。

请注意,表面上相似

const B &b = B();

确实有明确的行为;临时对象的生命周期B通过引用绑定来延长。这仅适用于引用变量,不适用于引用成员。

于 2012-09-26T13:35:30.690 回答
1

如果引用无效,这并不意味着它不可读。这意味着它没有引用有效的对象。它可能引用也可能不引用一些可访问的内存;如果是这样,您可能会或可能不会发现内存包含曾经存在的任何对象的残余物。

总而言之,行为是未定义的。

于 2012-09-26T13:36:28.477 回答
1

已分配给临时的内存B现在无效,但尚未用于任何其他用途。这就是为什么您的读取会产生上次存在的值。但是,这是未定义的行为。运行 valgrind 应该查明错误的位置。

如果您想知道“怎么可能”,这里有一个很好的答案,解释了在非常相似的情况下会发生什么。

于 2012-09-26T13:38:56.533 回答