1

I recently had a discussion where we argued if it is a good idea to make everything const if possible.

The argument did go like that: If I expose an internal part of the class by returning a non-const reference to it, I should not make that getter const even if it is possible.

For example:

  class Foo
  {
     std::unique_ptr<int> bar;

  public:
     Foo()
        : bar{std::make_unique<int>(10)}
     {
     }

     int& getBar() const // <-- we argued about that const here
     {
        return *bar;
     }
  };

  int main()
  {
     const auto foo = Foo{};
     foo.getBar()++;
  }

The code from above only works because the int is not stored within the memory of Foo itself. If I would replace the unique_ptr with a normal int but keep the public interface of the class the same the compiler will output an error:

  class Foo
  {
     int bar;

  public:
     Foo()
        : bar{10}
     {
     }

     int& getBar() const
     {
        // error: binding reference of type 'int&' to 'const int' discards qualifiers
        return bar;
     }
  };

  int main()
  {
     const auto foo = Foo{};
     foo.getBar()++;
  }

Is it a good idea to intentionally make a getter function non-const if it exposes something internal of the class as a non-const reference?

9

A class's interface needs to protect its internal state so that its invariants cannot be violated by outside users. (Within reason, of course. C++ makes it impossible to protect against all modifications.)

An implicit invariant of a const object is that its logical state (whatever that is - the definition of logical state for a class is up to its author, and may differ from simply the values of its bits) cannot change.

So a const function that allows the user to modify the logical state is a bad idea, since it makes it easy to break the invariant,.

Thus the question of whether getBar() should be const comes down to whether the value behind the pointer is part of the logical state of the object or not. Perhaps in the real code it is a back reference to some manager object that created this object (not likely for a unique_ptr, but it could be in other cases). In that case, returning a non-const reference from a const member function would be fine.

But in the case of a unique_ptr, it's more likely that the value behind the pointer is actually part of the logical state, and as such returning a non-const reference from a const function is a bad idea.

  • I would go further and say returning a non-const reference to the object's internal state is a bad idea whether the getter is const or not. – Daniel T. Jul 4 '17 at 1:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.