Search code examples
c++oopreferenceconstants

When is it a good idea to return a const reference in C++?


Are there any articles about when it is a good practice to use const references as return types?

This is less of a question about a particular issue and more of an educative question.

We are in the process of migrating to modern C++ from a somewhat rudimentary level of C and me and my colleague are tasked with mentoring a group of other people on C++ since we are pretty comfortable with the language.

I am having a slight argument with said colleague about this subject. The example at hand is a simple class:

class Cls
{
private:
    vector<int> vec;

public:

    Cls() { /* put 3 random values in vec */ }

    const vector<int>& getVec() {return vec; }
};

My argument from the fact that:

  1. References should be used as returns since you don't lose time copy-ing stuff. It's straight-up speedup.

  2. References should be const since if you return just a reference to vec then anyone can mutate it using just the getter, which is obviously bad. Hence we need to return const TYPE& for getters.

My colleague supports just returning vector<int> and be done with it. His arguments are:

  1. It's an advanced concept that should not be taught from the start. We can just return by value from getters for now (and thus produce copies) and make the transition to reference later, when they are capable of understanding what happens behind the scenes. (My opinion being that since I consider using this to be very good practice it should be taught and enforced from the start so people get used to doing it, and then the part where we make sure everybody really understands what const references mean can come later since we might not have time to get the mentees to the level where can juggle references.)

So my questions basically are:

  1. Are there some articles about good practices on this subject and when to use const references instead of values as returns?

  2. While me and my colleague are fairly comfortable with C++ neither of us has worked professionally with it so... is there a standard or convention in the industry for this question?


Solution

  • The decision of when to return by-reference vs. by-value is not just a matter of performance, it's a matter of code semantics (although performance usually matters a lot when coding in C++).

    Some notable examples of returning by-reference are:

    • a getter is often expected to return a const-reference to the actual member, unless that member is cheap to copy
    • to allow for method or operator chaining, returning a reference to the current object (*this)

    The question of when to return by-reference actually boils down to a broader question of how to manage object's lifetime safely. C++ Core Guidelines on object's lifetimes is a good resource to adhere to.

    If the object being referred-to outlives the function invocation, then it's generally safe to return it by-reference.

    So:

    • this, class members and objects with static storage duration: safe to return it by-reference

    • locals and function's input arguments: not safe to return by-reference. For input arguments, it applies even to const-references, since they can refer to temporaries. For example:

      std::string const& badFunc(std::string const& arg) {
        return arg; // not a good idea
      }
      
      int main() {
        std::string const& x = badFunc("abc");
        // now x contains a dangling reference!
        // ...
      }