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.
12 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.
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
constthen modifying the returned object using that reference is a compile-time error.