5

Can the C++ compiler assume a 'const bool &' value will not change?

For example, imagine that I have a class:

class test {
public:
  test(const bool &state)
    : _test(state) {
  }

  void doSomething() {
    if (_test) {
      doMore();
    }
  }
  void doMore();

private:
  const bool &_test;
};

And I use it as follows:

void example() {
  bool myState = true;
  test myTest(myState);

  while (someTest()) {
    myTest.doSomething();
    myState = anotherTest();
  }
}

Is it allowed by the standard for the compiler to assume _test's value will not change.

I think not, but just want to be certain.

zwol
  • 135,547
  • 38
  • 252
  • 361
WilliamKF
  • 41,123
  • 68
  • 193
  • 295
  • I guess the constructor should rather accept a non-const reference. You are at risk of binding the reference to a temporary, whose life-time ends with the constructor call and using a dangling reference in `doSomething` – UncleBens Feb 26 '11 at 22:04
  • @UncleBens - or even better pointer-to-const, which prevents the caller accidentally referring to a temporary, but still lets them easily refer to an object that really is const, or that they have by const reference. With effort they can of course still get a pointer to a temporary, but making that effort puts the fault on them: `template const T* blow_leg_off(const T &t) { return &t; }`, `test myTest(blow_leg_off(true));`. Just initializing a const reference member is fraught with peril, you could accidentally get an implicit conversion, so maybe use a pointer for the member too. – Steve Jessop Feb 27 '11 at 02:23

3 Answers3

7

No. Just because your reference (or pointer) is a const does not stop someone else from having a non-const reference. Like this:

int main(void) {
  bool myState = true;
  test myTest(myState);
  std::cout << myTest.getState() << std::endl;
  myState = false;
  std::cout << myTest.getState() << std::endl;
}

Or even more simply:

bool a = true;
const bool& b = a;
a = false; // OK
b = true; // error: assignment of read-only reference ‘b’
Josh Lee
  • 171,072
  • 38
  • 269
  • 275
  • And don't forget the ominous `const_cast` or, for more complicated objects, the `mutable` attributes and their mis-uses. – Matthieu M. Feb 26 '11 at 18:14
5

const Type & r means that "the value of r cannot be changed through this reference to it" - but it may well be changed by other code that has direct access to the referenced value (or through a non-const reference or pointer). The same goes for a const Type * p: "the value that p points to cannot be changed through this pointer to it.

Aasmund Eldhuset
  • 37,289
  • 4
  • 68
  • 81
3

You're right, it can't assume that, because the value of the referand of _test might be modified in the implementation of doMore, which is unavailable at compile-time. Since in this case myState is not a const object, it's valid (for example) for doMore to cast away const and modify it. Note valid, not advisable ;-)

And in general, doMore might call functions that have other pointers/references to the same bool object by another route. In your example there are no other references taken, so if the compiler can see all the code that might possibly reference it (including the definition of doMore), and none of it modifies the value, then it can make the assumption.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699