Question

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.

Était-ce utile?

La solution

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.

Autres conseils

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.
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top