14

In the code snippet, I am able to access the private member variable outside the class scope. Though this should never be done, why is it allowed in this case? Is it a bad practice to receive a returned private variable by reference ?

#include <iostream>
#include <cstdlib>

class foo
{
    int x;
    public:
        foo(int a):x(a){}
        int methodOne() { return x; }
        int& methodTwo() { return x; }
};

int main()
{
    foo obj(10);
    int& x = obj.methodTwo();
    x = 20;              // With this statement, modifying the state of obj::x

    std::cout << obj.methodOne();
    getchar();
    return 0;
}

And regarding this method, what does the return type convey ? And also when should I have return type of this kind ?

int& methodTwo() { return x; }

PS: I am sorry if the subject line is vague. Can someone change it to the content relevant here. Thanks.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
Mahesh
  • 34,573
  • 20
  • 89
  • 115

5 Answers5

28

private does not mean "this memory may only be modified by member functions" -- it means "direct attempts to access this variable will result in a compile error". When you expose a reference to the object, you have effectively exposed the object.

Is it a bad practice to receive a returned private variable by reference ?

No, it depends on what you want. Things like std::vector<t>::operator[] would be quite difficult to implement if they couldn't return a non-const reference :) If you want to return a reference and don't want clients to be able to modify it, simply make it a const reference.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
  • 1
    For people passing by : [this question](http://stackoverflow.com/questions/8005514/is-returning-references-of-member-variables-bad-pratice) suggests it can be dangerous to return a reference to your class members. – Arthur Jun 12 '13 at 23:19
  • 1
    @Arthur: Yes, as I said, it depends on what you want to do. It works just fine for `std::vector` -- but there are plenty of cases where it is the wrong thing to do too. – Billy ONeal Jun 12 '13 at 23:28
5

Returning private members as reference is perfectly valid and the programmer who writes a class is responsible to carefully choose if this should be allowed. This link gives an example when this can be done.

seaotternerd
  • 6,298
  • 2
  • 47
  • 58
Donotalo
  • 12,748
  • 25
  • 83
  • 121
3

This code:

 int& methodTwo() { return x; }

Means that the function returns a reference to an integer. Just like when passing a value by reference to a function, if the return value of methodTwo gets changed, so does the value that methodTwo returned. In this case, class field x.

In the code you have written, this means that you are letting the private variable x escape its scope (a class field) and be passed around in the outside world. This certainly is a bad practice (because x can be changed in ways that may break class foo, but it is certainly allowable.

Remember public/private/protected are compile-time only. Once your application gets compiled, private fields sit next to public fields and there is no protection against modification. The same is true for managed languages like C# and Java.

You should generally avoid returning references because it makes it crazy-hard to understand when constructors/destructors get called. However, returning a reference can be faster. If your method returned a struct type that was HUGE, returning a const reference to that same struct type should only take four-to-eight-bytes (a pointer to that object). However, there are better ways to optimize for this sort of thing.

Chris Smith
  • 18,244
  • 13
  • 59
  • 81
  • 3
    I strongly Strongly STRONGLY disagree on the "you should avoid returning references" point -- given that the compiler is free to elide calls to the copy constructor if you return by value, the only thing you gain in many cases by returning by value is slow debug builds (because the compiler does RVO/NRVO on you in release mode). – Billy ONeal Jan 16 '11 at 17:34
  • 3
    Not being a guru-level C++ user, I reserve the right to be wrong :) But won't you get undefined behavior if you return a reference to a local variable? (I.e., you are left with a pointer to some random spot on the stack?) – Chris Smith Jan 16 '11 at 17:38
  • 1
    That is correct. Attempting to access a destroyed variable via reference results in undefined behavior. But for things like class getters returning by reference is normal and expected behavior. – Billy ONeal Jan 16 '11 at 17:39
1

Like Donotalo said, it is perfectly valid. The idea of having private members is to disallow other classes/functions to access the private member of the class without your permission. If you are happy to make a function to allow other classes/functions to access your private members, the compiler has nothing against that really :-)

Usually, it is useful to have a private member and have a get function to allow other classes/functions to get the value of the function, but only the class will be able to change it.

Rafid
  • 18,991
  • 23
  • 72
  • 108
-1

I am able to access the private member variable outside the class scope

If you are referring to the x in main() then that is different from the x declared in class foo. If you try to access the obj.x then the compiler will definitely complain.

Is it a bad practice to receive a returned private variable by reference ?

There is nothing wrong in "receiving" the reference to a private member. But giving out the reference to a private member makes declaring it private useless. By declaring a variable to be a private member you restrict the access to that member only to the class' methods.

regarding this method, what does the return type convey ? And also when should I have return type of this kind ?

Not sure as to which method you are referring to?!?!?!

yasouser
  • 5,113
  • 2
  • 27
  • 41
  • 2
    Really? It makes it useless? How do you explain `std::vector::operator[]` then? Whatever buffer pointer the vector is using is not exposed to the world, but the data is (and should be, given the point of the vector) – Billy ONeal Jan 16 '11 at 17:38