Const Class

I dont really understand what's the difference between these:

1
2
3
  int get() const {return x;}        // const member function
  const int& get() {return x;}       // member function returning a const&
  const int& get() const {return x;} // const member function returning a const&  


And the difference between:

1
2
  int get() {return x;}
  int& get() {return x;}


Can somebody explain these to me..

Thanks..
Last edited on
The declaration int get() const, which is likely a member function, promises that it does not change the instance upon which it is called. It promises to treat the instance as const, and can only change member variables declared as mutable (a rare exception).

To be clear,

1
2
3
T n;

n.get();


Where 'get' is declared const promises not to change n.

This applies, too, to your third example.

When the function is not declared const, it is suggestive that it will change n.

As to returning a const int, especially as a reference, the calling code is restricted from changing the integer. If the returned reference is a member of n, this restricts the calling code from changing the value of that reference, which would have the effect of changing a member inside n if it did.

When returning an int (not a reference to an int), the calling code receives a copy, which it then "owns", and can change without impacting anything in n.

For the int & version, it depends on what was returned, but presumably the reference is to some member of n, and if the calling code changes the value stored at that reference, the corresponding member of n will be changed.

1
2
3
4
5
6
7
8
9
10
11
#include <iostream>
#include <map>

int main ()
{
  const std::map<char,int> first { {'a', 10}, {'b', 30} };

  std::cout << first[ 'a' ] << '\n'; // error: first is const
  std::cout << first.at( 'a' ) << '\n';
  return 0;
}

The map has both members operator[] and at(). There is no operator[](const key_type&) const but there is at(const key_type&) const.
For us, users of constant maps, the at() is our only option.


You ask difference of the return type of functions.
Can you explain the difference of:
1
2
3
int func( int );
int func( int& );
int func( const int& );
@keskiverto
I know the difference between the first and the second line, but not the third one
Third way to see the three:
1
2
3
4
5
6
7
8
9
10
11
int main() {
  int value = 42;

  int copy = value;
  int& ref = value;
  const int& cref = value;

  copy = 7; // ok. Copy changes, value does not 
  ref = 13; // ok. Value changes
  cref = 3; // error: cannot change constant object
}

A reference is not a copy. We can access the referred to object via the reference.

In the program above we do not need the reference, for we could simply: value = 13;

1
2
3
4
5
6
7
8
void func( int& );

int main() {
  int x = 7; int y = 42;
  func( x ); 
  func( y ); 
  // use x and y
}

The code of function func() has a reference, but it does not know what variable to. It can modify our x and y without knowing who they are.

The by reference parameters are a way for a function to return data to its caller.

There is a second reason to pass parameter by reference: it is not a copy. Complex object can be expensive to copy. Making a reference is very cheap.
1
2
double func( std::vector<double> ); // by value
double func( std::vector<double>& ); // by reference 

The by value version has to create a whole copy of a vector. You need memory for the copy and you need to copy the elements. All extra work.

Alas, what if the func() modifies our vector? That was the first purpose of by reference parameters. We don't wan't that. We just wan't to avoid the copy. What to do?
double func( const std::vector<double>& ); // by reference, but function cannot modify

We have a reference. We can access the referred to object, but we can't modify it via the reference.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
struct X {
  int x = 7;
  int& get() {return x;} // #1
  const int& get() const {return x;} // #2
};

int main() {
  X sample;
  sample.get() = 42;
  cout << sample.get(); // prints 42
  // sample calls #1 because it is not const

  const X fail;
  fail.get() = 42; // error: cannot modify const reference
  cout << fail.get(); // ok
  // fail calls #2 because it is const
}

A function can modify caller's objects, if the function has by reference parameters.

Here a member function returns a reference. We, the caller of sample.get() can modify the 'sample.x' via that reference.
Topic archived. No new replies allowed.