3

I am currently learning the basics of C++ and I have found the following code:

#include <iostream>
using namespace std;

class MyClass {
    int x;
public:
    MyClass(int val) : x(val) {}
    int& get() {return x;}
};

int main() {
  MyClass foo (10);
  foo.get() = 15;  
  cout << foo.get() << '\n';

  return 0;  
}

I don't understand why the line foo.get() = 15 works. To me it looks like a get and set at the same time. I guess it works due to the return type being int& and not only int.

Can someone explain to me how it works?

Thanks.

Niall
  • 30,036
  • 10
  • 99
  • 142
Scipion
  • 11,449
  • 19
  • 74
  • 139

4 Answers4

5

Your foo.get is returning a reference to an int (noted int&).

References can be assigned (so they are l-values). Read the wikipage on C++ references, it is explaining better than I have time to. Or read carefully a good C++ programming book, like e.g. Stroustrup's Programming : Principles and Practice Using C++ or a Tour of C++ or The C++ Programming Language (or all of them!)

As Neil Kirk commented, you could nearly see references as a pointer implicitly dereferenced. In other words, and if you are familiar with C, think of int* get() { return &x; } and *foo.get() = 15;

See also this reference vs. pointer question

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
2

The line works because the function is returning a reference, that's semantically equivalent to:

  int* get() {return &x;}

and:

  *foo.get() = 15;
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • 1
    @Josh -1, what is your point exactly? Paul is talking about this specific use, not all uses of references ever. – M.M Sep 10 '14 at 20:40
  • @MattMcNabb thanks. of course the compiler enforces a different set of *rules* on *references* with respect to *pointers*, such as making it *very* difficult to reseat or zero a *reference*, but the topic is deep enough to be well outside the scope of both the OP's question and SO itself. – Paul Evans Sep 10 '14 at 20:56
1

In C++ the return value from function is a variable which it is stored in the stack or the heap, but without a known name to you. so here

int& get() {return x;}

so foo.get() as one group ( foo.get() ) return a variable, in your case this is a by reference variable which mean the return of (foo.get()) is the variable x inside the foo class.

so doing foo.get() = 15 is same as doing foo.x = 15 because its return by reference.

Note : foo.x = 15 will give compiler error because x is private by default, but its very okay to return it as reference to access it.

Creative Coder
  • 409
  • 6
  • 15
0

Code written is perfectly valid. You return non-constant reference to user code. User assigns to it, so your class member variable gets new value.

It seems that you are worrying about preserving encapsulation here. From this perspective, in a form you written it, your getter is not correct. Most times we return either a value or a constant reference:

int get() { return x; }

const int& get() { return x; }

This way user will not be able to mutate member variable returned. Getter is a dumb "return me" function, so, most times, we assume that it shall not mutate internal class state. To be cautious, we also often make getters constant members:

const int& get() const { return x; }

Of course there are exceptions (notably, lazy eveluation). And also, user could cast out constness. But it is another story.

See also: Const-correctness, Mutator_method, The Definitive C++ Book Guide and List ("Best practices" and "Intermediate")

Community
  • 1
  • 1
Ivan Aksamentov - Drop
  • 12,860
  • 3
  • 34
  • 61