允许以下代码
struct Foo {
int x;
};
Foo f;
Foo & f_ref = f;
(&f) -> ~Foo ();
new (&f) Foo ();
int x = f_ref .x;
但不允许使用以下代码
struct Foo {
const int & x; // difference is const reference
Foo (int & i) : x(i) {}
};
int i;
Foo f (i);
Foo & f_ref = f;
(&f) -> ~Foo ();
new (&f) Foo (i);
int x = f_ref .x;
因为$3.8/7
如果在对象的生命周期结束之后,在对象占用的存储空间被重用或释放之前,在原始对象占用的存储位置创建一个新对象,一个指向原始对象的指针,一个指向原始对象的引用引用原始对象,或者原始对象的名称将自动引用新对象,并且一旦新对象的生命周期开始,可用于操作新对象,如果:
- 原始对象的类型不是 const 限定的,并且,如果是类类型,则不包含任何类型为 const 限定或引用类型的非静态数据成员...
我可以理解f.x
当 f 不再存在时引用如何失效,但我不明白为什么f_ref
应该仅仅因为它的成员之一是 const 和/或引用而不是其他原因而失效:它是对 aFoo
之前和是对aFoo
之后的引用。
有人可以解释这种情况背后的理由吗?
编辑
感谢您的回答。我不购买“保证它不会改变”的论点,因为我们目前不允许优化器缓存引用,例如:
struct Foo {
const int & x;
Foo (const int & i) : x(i) {}
void do_it ();
};
int i;
Foo f (i);
const int & ii = f.x;
f .do_it (); // may modify i
std :: cout << ii; // May NOT use cached i
我看不到如何do_it
允许使引用的值无效,但operator new
不是—— 序列点使缓存的值无效:为什么要免除 delete/placement-new?