C++ 为什么从临时初始化的引用成员仍然可读?
可能重复:C++ 为什么从临时初始化的引用成员仍然可读?,c++,reference,initialization,C++,Reference,Initialization,可能重复: 这个问题与我刚才问的另一个问题直接相关: 假设我们有一个类,该类具有某个其他类的引用成员,该类被初始化为构造函数中的临时变量: #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
这个问题与我刚才问的另一个问题直接相关: 假设我们有一个类,该类具有某个其他类的引用成员,该类被初始化为构造函数中的临时变量:
#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
先前占用的内存在引用之前不会被覆盖。下次运行程序时,任何事情都可能发生
请注意,表面上相似的
const B &b = B();
有明确的行为;临时
B
的生存期通过引用绑定来延长。这只适用于引用变量,而不适用于引用成员。未定义的行为。在您的情况下,临时B
先前占用的内存在引用之前不会被覆盖。下次运行程序时,任何事情都可能发生
请注意,表面上相似的
const B &b = B();
有明确的行为;临时
B
的生存期通过引用绑定来延长。这只适用于引用变量,而不适用于引用成员。如果引用无效,并不意味着它不可读。这意味着它没有引用有效的对象。它可能涉及也可能不涉及某个可访问内存;如果是的话,你可能会发现,也可能不会发现记忆中包含了曾经存在过的任何物体的残余物
总之,行为是未定义的。如果引用无效,并不意味着它不可读。这意味着它没有引用有效的对象。它可能涉及也可能不涉及某个可访问内存;如果是的话,你可能会发现,也可能不会发现记忆中包含了曾经存在过的任何物体的残余物
总而言之,行为未定义。分配给临时
B
的内存现在无效,但尚未用于任何其他用途。这就是为什么您的读取会产生上次存在的值。但是,这是未定义的行为。运行valgrind应该可以精确定位错误的位置
如果您想知道“怎么可能”,这里有一个解释,说明在非常类似的情况下会发生什么。分配给临时
B
的内存现在无效,但尚未用于任何其他用途。这就是为什么您的读取会产生上次存在的值。但是,这是未定义的行为。运行valgrind应该可以精确定位错误的位置
如果你想知道“这怎么可能”,这里有一个解释,说明在非常相似的情况下会发生什么。这是未定义的行为。没有“为什么”。内存仍然包含值
23
。请看Eric Lippert的杰出答案:也回答了您的问题。投票以重复方式关闭。在中间添加两个函数调用,您可能会得到一些垃圾…这是未定义的行为。没有“为什么”。内存仍然包含值23
。请看Eric Lippert的杰出答案:也回答了您的问题。投票以重复方式关闭。在中间添加几个函数调用,您可能会得到一些垃圾。。。