I am confused with const T& and T in function return.

For example, I have a class A:

class A { private: vector<T> my_vector_; public: T fun1() { return my_vector_.at(0); } const T& fun2() { return my_vector_.at(0); } } 

Then,

Class A a; T b = a.fun1(); const T& c = a.fun1(); const T& d = a.fun2(); 

What's the difference for these three case? Thank you.

1

2 Answers

T b = a.fun1(); 

Here, b holds a copy of the element at position 0 of the vector. Meaning, any modification made to the former won't affect the latter.

const T& c = a.fun1(); 

fun1 returned an object by value, and you've used a reference to const to refer to it. Taking this into account, the object is really "floating in space". Its lifetime will be bound to that of c, but is't still a copy of the original from the vector.

const T& d = a.fun2(); 

fun2 returned a reference to const to an element inside of the vector, and you bound d to it. From now on, the latter is an alias to the former.

2

When you return an object by reference (i.e. T& fun(...) { ...}) then you are returning the same object that you were using inside your function, while when you return the object by value (i.e. T fun(...) { ...}) the object is copied before returning the function.

You can check this if you print your object's memory address inside the function and after it has been returned:

printf("%p\n", &my_object); 

The const only says that the compiler should make sure you are not modifying the object from the outside (i.e. you cannot do: object.field = value).

I have arranged this sample that shows all the differences between those approches:

#include <stdio.h> class X { public: int i; X(); X(const X&); }; // Copy constructor X::X(const X& x) { printf("Copy constructor invoked\n"); } // Default constructor X::X() : i(0) { printf("Creating a object\n"); } X my_fun_1(X& x) { return x; } X& my_fun_2(X& x) { return x; } const X& my_fun_3(X& x) { return x; } int main () { X x0; printf("\nInvoke my_fun_1\n"); X x1 = my_fun_1(x0); printf("\nInvoke my_fun_2\n"); X& x2 = my_fun_2(x0); printf("\nInvoke my_fun_3\n"); const X& x3 = my_fun_3(x0); printf("\nResults:\n"); printf("x0 => %p\n", &x0); printf("x1 => %p\n", &x1); printf("x2 => %p\n", &x2); printf("x3 => %p\n", &x3); x0.i = 1; x1.i = 1; x2.i = 1; //Compile-time error: x3.i = 1; return 0; } 

Compile and run it, the output should be:

$ g++ a.cpp && ./a.out Creating a object Invoke my_fun_1 Copy constructor invoked Invoke my_fun_2 Invoke my_fun_3 Results: x0 => 0x7fff8710cce0 x1 => 0x7fff8710ccf0 x2 => 0x7fff8710cce0 x3 => 0x7fff8710cce0 

Notice:

  • If you don't use & then the copy constructor is used
  • If you use const then modifying the returned object using that reference is a compile-time error.
1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy