1

in C++ is it a bad practice to use reference in place of getters?

for example:

class X
{
    int mP;
 public:
    const int& P;
    X():P(mP){}
}; 

and later

X xl;
int h = xl.P;
Shubham
  • 172
  • 8
  • The above code is extremely dangerous, as you lack a copy constructor, and the copy constructor you get by default does not do what you want done. :) – Yakk - Adam Nevraumont Nov 14 '13 at 20:10
  • 1
    Why not make `mP` public? – juanchopanza Nov 14 '13 at 20:12
  • The whole point of getters/setters is that the object knows when data changes; its a level of abstraction. If you are trying to get around this, do what @juanchopanza says. – clcto Nov 14 '13 at 20:13
  • I do not have any requirement like this but, I was just wondering if this can do any harm. @Yakk will a copy constructor come into picture while initializing a reference?? – Shubham Nov 14 '13 at 20:20
  • @user2173884 If you interested in such questions, then you are ready to pick theese classic books: *Effective C++* series by Scott Meyers and *Exceptional C++* series by Herb Sutter. [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list?rq=1) – Ivan Aksamentov - Drop Nov 14 '13 at 20:42
  • Yes. `X alice; X bob = alice;` will call the copy constructor, and `bob.P` will be a reference to `alice.mP`. What worse, `X make_X(); X bob = make_X();` will result in using `bob.P` being undefined behavior. Storing references in a `class` or `struct` is dangerous, as assignment and copy rarely does what you want it to do, especially if the type isn't "all reference" or "all non-reference". – Yakk - Adam Nevraumont Nov 14 '13 at 22:00

2 Answers2

1

Just think about refactoring to make the access thread safe, that won't work well this way and require a lot of changes in the client classes/functions.

If you have class members, that are guaranteed not to be changed over lifetime of the instance, you can simply provide const int P; and initialize it properly in your class' constructors.

If the value is to be visible class wide use a static const int P;

In any other case use a public getter:

int P() const; // a return type of 'const int &' would be redundant  

1st shot implementation:

int X::P() const
{
    return mP;
}

Thread safe implementation:

class X {
{
    // ...
private:
    // ...
    mutable std::mutex internalDataGuard;
};

int X::P() const
{
    std::lock(internalDataGuard);
    return mP;
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
  • @user2173884 Depend's on your use case. But if you abstract it out in your designs early (as you don't do with `public const int& P;`), will make it easier to scale out later. I think I have explained the exceptional cases well. – πάντα ῥεῖ Nov 14 '13 at 22:13
0

None of this is good:

class X { public: int x; };
class X {
    private: int m_x;
    public: const int& get() const { return m_x; }
    public: void set(const int& other)  { m_x = other; } 
};
class X {
    private: int m_x;
    public: const int& x() const { return m_x; }
    public: void x(const int& other)  { m_x = other; } 
};
class X {
    private: int m_x;
    public: const int& x() const { return m_x; }
    public: int& x()  { return m_x; }
};

Pick one, it's a design decision.

Having 'const int& x' to publish the private member will work:

class X {
    private: int m_x;
    public: const int& x;
    public: X() : m_x(0), x(m_x) {}
    // Take care for copy and assignment
};

The cost is a larger memory footprint.

  • How would this cost larger memory footprint? – Shubham Nov 14 '13 at 20:58
  • @user2173884 the class stores x plus the reference to x –  Nov 14 '13 at 21:00
  • I guess Reference do not take any memory. they are resolved during compile time, they are just an alias in variable table created by compiler which does not exist after linking. – Shubham Nov 14 '13 at 21:03
  • @user2173884 Nope - they take the same space as a pointer does. –  Nov 14 '13 at 21:05
  • Indeed. I just checked it actually take pointer size. Valid point to not to use this. – Shubham Nov 14 '13 at 21:18