简体   繁体   中英

const reference to object with mutable members

Suppose that I have a class with a mutable member, and I take multiple const references to an object of that class. Does the standard guarantee that these references will stay in sync with one another? An example is below.

Motivation: I believe that I have read that the compiler has multiple options on how to extend the lifetime of objects with const references, and some of them actually involve copying the object (which of course may subvert one of the reasons for using references in the first place, but may be necessary to guarantee the object's survival). If this is true, then can the multiple references actually start to act like multiple objects (with different values for the mutable members)?

Example:

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;
}

Here is how I am interpreting this. a has already gone out of scope, so the compiler had to either "keep the original object alive" somehow (which doesn't mix well with my basic understanding of how the stack works) or make a copy of it for each instance of B (which the compiler assumes to be safe because it is const ). However, I did something that may have changed the mutable part of one of these instances. Can b1.a and b2.a actually differ at this point?

If the answer is "yes," then this is reasonable, since I wouldn't expect otherwise. But if the answer is "no," I am very interested in how it works.

It seems you were expecting lifetime extension due to reference binding. Nope, sorry. Lifetime extension is for temporaries, not objects that already exist with a scope and a name.

Even if you'd passed a temporary to B 's constructor, it'd still only be extended until the end of that statement — the extension isn't transitive along a whole chain of reference bindings (and it doesn't work on member references).

Therefore, you're trying to access data through a dangling reference, and your program has undefined behaviour. Expect any result, or no result. Neither const nor mutable has anything to do with it.

If you're wondering where physically your observations originate, that's something to take up with your preferred deity .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM