【发布时间】:2011-11-27 01:28:53
【问题描述】:
在my answer 到this question 的讨论之后,显然:
以下代码是允许的
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 不再存在时对 f.x 的引用如何失效,但我不明白为什么 f_ref 应该被失效纯粹因为它的成员之一是 const 和/或引用而不是其他: 之前是对Foo 的引用,之后是对Foo 的引用。
有人能解释一下这种情况背后的原因吗?
编辑
感谢您的回答。我不赞成“保证它不会改变”的说法,因为我们不允许目前允许优化器缓存引用,例如:
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 不允许——Sequence points invalidate cached values:为什么要豁免 delete/placement-new?
【问题讨论】:
-
没关系,OP编辑了代码。
-
我不明白,
do_it怎么能修改i? -
@uncleBens: 例如
do_it中的const_cast<int &>(x) = 1;是完全可以的,因为x的引用实际上是一个可变的int对象。如果这就是do_it所做的,那么执行const int i; Foo f(i); f.do_it();将是一个错误 (UB),但使用非 consti就可以了。
标签: c++ reference constants c++11 placement-new