Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对具有可变成员的对象的常量引用_C++_Reference_Constants_Mutable - Fatal编程技术网

C++ 对具有可变成员的对象的常量引用

C++ 对具有可变成员的对象的常量引用,c++,reference,constants,mutable,C++,Reference,Constants,Mutable,假设我有一个具有mutable成员的类,我对该类的一个对象进行了多个const引用。标准是否保证这些引用彼此保持同步?下面是一个例子 动机:我相信我已经读到,编译器在如何延长带有const引用的对象的生命周期方面有多种选择,其中一些实际上涉及到复制对象(当然,这可能会首先破坏使用引用的原因之一,但可能是保证对象生存所必需的)。如果这是真的,那么多个引用是否真的可以开始像多个对象一样工作(对于可变的成员具有不同的值) 例如: class A { public: mutable int

假设我有一个具有
mutable
成员的类,我对该类的一个对象进行了多个
const
引用。标准是否保证这些引用彼此保持同步?下面是一个例子

动机:我相信我已经读到,编译器在如何延长带有
const
引用的对象的生命周期方面有多种选择,其中一些实际上涉及到复制对象(当然,这可能会首先破坏使用引用的原因之一,但可能是保证对象生存所必需的)。如果这是真的,那么多个引用是否真的可以开始像多个对象一样工作(对于
可变的
成员具有不同的值)

例如:

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
的每个实例制作一份副本(编译器假定它是安全的,因为它是
常量
)。但是,我做了一些事情,可能更改了其中一个实例的
可变
部分。在这一点上
b1.a
b2.a
是否确实有所不同


如果答案是“是”,那么这是合理的,因为我不希望出现其他情况。但是如果答案是“否”,我对它的工作原理非常感兴趣。

似乎您希望由于引用绑定而进行生存期扩展。不,对不起。生存期扩展是针对临时对象的,而不是已经存在的具有范围和名称的对象

即使您已将临时构造函数传递给
B
的构造函数,它仍然只能扩展到该语句的末尾(并且它对成员引用不起作用)

因此,您试图通过悬空引用访问数据,而您的程序有未定义的行为。请期待任何结果,或者没有结果。
const
mutable
与此无关


如果您想知道您的观察结果从何而来,这是值得考虑的。

似乎您希望由于引用绑定而获得生存期扩展。不,对不起。生存期扩展是针对临时对象的,而不是已经存在的具有范围和名称的对象

即使您已将临时构造函数传递给
B
的构造函数,它仍然只能扩展到该语句的末尾(并且它对成员引用不起作用)

因此,您试图通过悬空引用访问数据,而您的程序有未定义的行为。请期待任何结果,或者没有结果。
const
mutable
与此无关


如果你想知道你的观察结果是从哪里来的,那就是问题所在。

这里没有生存期扩展。你不能只是在程序中的一个随机位置链接一个引用,然后扩展一个任意变量的生存期。“生存期扩展”我指的是const引用的普通用法。例如,“C++故意指定将临时对象绑定到堆栈上的const的引用,将临时的生存期延长到引用本身的生命周期,从而避免了否则将是一个常见的悬空引用错误。”(在下一篇评论中继续)但同一段给出了我问题的真正答案:“(注意,这只适用于基于堆栈的引用。它不适用于作为对象成员的引用。)”@sasquires:life extension是针对临时对象的,而不是针对已经存在且具有作用域和名称的对象。GotW引号中没有特定的临时对象。啊,不知怎的,我跳过了“临时”这个词在那句话中也是如此。好吧,这是有意义的,我的问题不是。这里没有生存期扩展。你不能只是在程序中的随机位置链接引用,然后扩展任意变量的生存期!我指的“生存期扩展”是常量引用的普通扩展。例如,请参阅:“但是,C++故意指定将临时对象绑定到堆栈上的const的引用,将临时的生存期延长到引用本身的生存期,从而避免否则将是常见的悬空引用错误。”(继续在下一条注释中)但同一段给出了我问题的真正答案:“(注意,这只适用于基于堆栈的引用。它不适用于作为对象成员的引用。)@sasquires:life extension是针对临时对象的,而不是针对已经存在且具有作用域和名称的对象。GotW引号中包含特定的临时对象。啊,不知怎的,我在那句话中也跳过了“临时”一词。好吧,这是有意义的,我的问题不是。“其中一些实际上涉及复制对象”也许是年龄,但我想不起有什么可能性。你能举个例子吗?“其中一些实际上涉及复制对象”也许是年龄,但我想不起有什么可能性。你能举个例子吗?