Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use const references instead of getter functions?

I just wondered if I could bypass using getters if I just allowed a const reference variable, as follows

#include <string>

class cTest
{
    private:
        int m_i;
        std::string m_str;

    public:
        const int & i;
        const std::string & str;

    cTest(void)
    : i(m_i)
    , str(m_str)
    {}
};

int main(int argc, char *argv[])
{
    cTest o;
    int i = o.i; // works
    o.i += 5; // fails
    o.str.clear(); // fails

    return 0;
}

I wonder why people do not seem to do this at all. Is there some severe disadvantage I am missing? Please contribute to the list of advantages and disadvantages, and correct them if necessary.

Advantages:

  1. There is no overhead through calls of getter functions.
  2. The program size is decreased because there are less functions.
  3. I can still modify the internals of the class, the reference variables provide a layer of abstraction.

Disadvantages:

  1. Instead of getter functions, I have a bunch of references. This increases the object size.
  2. Using const_cast, people can mess up private members, but these people are mischievous, right?
like image 603
Fabian Avatar asked Dec 11 '15 07:12

Fabian


People also ask

Can references be const?

The grammar doesn't allow you to declare a “const reference” because a reference is inherently const . Once you bind a reference to refer to an object, you cannot bind it to refer to a different object.

Can getters be const?

Having a const getter allows you to call it on const objects: const Object obj; obj. getReady(); This is only valid if getReady is marked as const .

Can a const reference refer to a non-const object?

No. A reference is simply an alias for an existing object.

When should we use a const reference and why?

Pass Using Const Reference in C++ Now, we can use the const reference when we do not want any memory waste and do not change the variable's value. The above code will throw a compile error as num = num +10 is passed as a const reference.


2 Answers

Some severe disadvantages indeed (aside from the 2nd disadvantage that you also mention which I also put in the "severe" category):

1) You'll need to supply (and therefore maintain) a copy constructor: the compiler default will not work.

2) You'll need to supply an assignment operator: the compiler default will not work.

3) Think carefully about implementing the move semantics. Again, the compiler default will not work.

These three things mean the const reference anti-pattern you propose is a non-starter. Don't do it!

like image 69
Bathsheba Avatar answered Oct 29 '22 11:10

Bathsheba


One advantage of getter functions is that you might at some point in time - want to alter returned value - and without getter function you cannot do it. This scenerio would require you to return non reference actually, which is less common in c++. [edit] but with move semantics instead of references this should be doable[/edit]

You might also want to put a breakpoint into getter function to learn who is reading its value, you might want to add logging, etc. This is called encapsulation.

Other advantage of getter is that in debug builds you can add additional checks/asserts on returned data.

In the end compiler will inline your getter functions, which will result in similar code to the one you propose.

some additional disadvantage:

1) template code will want to get values using function call, ie. size(), if you change it to const& variable then you will not be able to use it in some templates. So this is a consistency problem.

like image 23
marcinj Avatar answered Oct 29 '22 10:10

marcinj