请考虑以下代码:
#include <iostream>
struct A {
const char *name;
A() : name("A") {
std::cout << "A()\n";
}
virtual ~A() {
std::cout << "~A()\n";
}
};
class B {
const A& a;
public:
B() : a(A()) {
};
void print_data() const {
std::cout << a.name << '\n';
}
~B() {
std::cout << "~B()\n";
}
};
int main() {
B b;
b.print_data();
return 0;
}
GCC 4.4的输出是:
A()~A()A~B()
这对我来说很奇怪。我本来期望A的临时实例的副本绑定到B :: a或者在B()期间该临时实体被破坏。
基本上,我认为B :: a在b的生命期间始终是有效的参考。事实上,b.print_data()显然工作,编译器不会发出任何警告。
标准c ++ 98/03对此事有何评价?
答案 0 :(得分:5)
常数引用不会延长课堂时期的临时生活。就是这样。他们只在Foo const& f = Foo();
中执行此操作,其中foo
按值返回,但就是这样。
§12.2 [class.temporary]
p4有两种情况下,临时表在与完整表达式结束时不同的点被销毁。 [...]
p5第二个上下文是指引用绑定到临时的。除了下面指定的内容之外,引用绑定的临时对象或作为临时绑定对象的子对象的完整对象的临时对象的生命周期仍然存在。 构造函数的ctor-initializer(12.6.2)中的引用成员的临时绑定将持续存在,直到构造函数退出。
答案 1 :(得分:2)
您的代码涉及未定义的行为。当B的构造函数退出时,临时被破坏(C ++ 03,[class.temporary]):
构造函数的ctor-initializer(12.6.2)中的引用成员的临时绑定将持续存在,直到构造函数退出。
尝试更改为:
B() : a(A()) {
cout << "B()\n";
};
你会得到:
A() B() ~A() A ~B()