提问人:sasquires 提问时间:2/28/2018 更新时间:2/28/2018 访问量:932
对具有可变成员的对象的常量引用
const reference to object with mutable members
问:
假设我有一个具有成员的类,并且我多次引用该类的对象。该标准是否保证这些引用将彼此保持同步?下面是一个示例。mutable
const
动机:我相信我已经读到编译器在如何延长带有引用的对象的生命周期方面有多种选择,其中一些实际上涉及复制对象(这当然可能会颠覆最初使用引用的原因之一,但可能是保证对象生存所必需的)。如果这是真的,那么多个引用实际上可以开始像多个对象一样(成员的值不同)吗?const
mutable
例:
class A {
public:
mutable int x;
A( const int x ) : x( x ) {}
void f() const; // Actually changes 'x'.
};
class B {
public:
const A & a;
B( const A & a ) : a( a ) {}
void f() const { a.f(); }
};
int main() {
B * b1;
B * b2;
{
A a( 0 );
b1 = new B( a );
b2 = new B( a );
}
// Do something that would change a mutable variable in 'b1.a' but possibly not in 'b2.a'.
b1.f();
return 0;
}
以下是我对此的解释。 已经超出了范围,因此编译器必须以某种方式“保持原始对象处于活动状态”(这与我对堆栈工作原理的基本理解不太相符)或为每个实例制作它的副本(编译器认为这是安全的,因为它是)。但是,我做了一些可能改变了其中一个实例的部分。在这一点上可以并且实际上有所不同吗?a
B
const
mutable
b1.a
b2.a
如果答案是“是”,那么这是合理的,因为我不会期望其他情况。但如果答案是否定的,我对它的工作原理非常感兴趣。
答:
2赞
Lightness Races in Orbit
2/28/2018
#1
由于引用绑定,您似乎希望延长寿命。不,对不起。生存期延长适用于临时对象,而不是已存在的具有作用域和名称的对象。
即使你已经将一个临时的 to 的构造函数传递给了 ,它仍然只会被扩展到该语句的末尾——该扩展在整个引用绑定链中不是可传递的(并且它不适用于成员引用)。B
因此,您正在尝试通过悬空引用访问数据,并且您的程序具有未定义的行为。期待任何结果,或者没有结果。两者都与它无关。const
mutable
如果你想知道你的观察从何而来,那么这是你喜欢的神灵所要做的事情。
评论
0赞
Lightness Races in Orbit
2/28/2018
不,这里没有寿命延长。你不能只是在程序中的随机位置放置一个引用,然后延长任意变量的生存期!
0赞
sasquires
2/28/2018
我所指的“寿命延长”是常量引用的普通延长。例如,参见 GotW 88:“但是,C++ 特意指定将临时对象绑定到堆栈上的引用以进行 const,从而将临时对象的生存期延长到引用本身的生存期,从而避免了常见的悬空引用错误。(在下一条评论中继续)
0赞
sasquires
2/28/2018
但同一段给出了可能是我问题的真正答案:“(请注意,这仅适用于基于堆栈的引用。它不适用于作为对象成员的引用。
1赞
Lightness Races in Orbit
2/28/2018
@sasquires:生存期扩展适用于临时对象,不适用于已存在且具有作用域和名称的对象。GotW 引用执行特定的临时对象。
0赞
sasquires
2/28/2018
啊,不知何故,我也跳过了那句话中的“临时”这个词。好吧,这是有道理的,我的问题没有。
评论