struct T {
~T() { cout << __FUNCSIG__ << endl; }
};
T t1;
struct A {
T & t;
A( T & ta): t(ta) { }
~A() { }
};
{
A a(t1);
}
puts("after a");
对于A的引用成员t, A与t是使用关系, A并不负责t的生命期管理, 不拥有t, 它只是假设它想使用t的时候t所引用的真正对象是可用的. t仅是另一对象的别名, 在技术上, 引用即指针.
A无法保证自构造完成后, 直到a对象被销毁之前, t所指向的对象都是可用的. 如下面:
T t = new T();
A a(*t);
delete t;
a.access_to_t(); // 显然可能是非法的, 但编译器不能检测到这样的错误.
所以, 引用一定指向一个合法的既存的对象, 或引用不需要象指针一样检查是否为NULL的说法可能会误导. 在技术细节上, 引用就是指针.
另一种说法是, 引用不能被赋值以指向另一个对象. 这样的限制只是语法层面的, 很容易被灵活的C++机制所骗过:
struct A{
int i;
A( int i ): i(i) { }
void print(void) { cout << i << endl; }
};
A a1(1);
A a2(2);
union {
A * ap;
A & a;
} x = { &a1 };
x.a.print();
x.ap = & a2;
x.a.print();
第一个 x.a.print() 当然会显示1, 因为引用a 指向的是第一个对象a1.
通过对ap赋值为另一个对象a2, 引用a 所指向的真正对象被稍稍地改变了. 所以第二个调用输出2
阅读(625) | 评论(0) | 转发(0) |