Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do functions return the result object by value or by reference?

When a function (callee) returns an object to the caller function, is it returned by value or by reference?

I have written a function which builds a large vector when called. I want to return this vector to the calling main function by constant reference so I can do some further processing on it.

I was in doubt because I was told that when a C++ function returns and terminates, all the variables/memory associated with that function, get wiped clean.

struct node {
    string key;
    int pnum;
    node* ptr;
};

vector<vector<node>> myfun1(/* Some arguments */) {
    /* Build the vector of vectors. Call it v. */
    return v;
}

int main() {
    a = myfun1(/* Some arguments */)
}
like image 300
smilingbuddha Avatar asked Sep 05 '25 17:09

smilingbuddha


2 Answers

C++ functions can return by value, by reference (but don't return a local variable by reference), or by pointer (again, don't return a local by pointer).

When returning by value, the compiler can often do optimizations that make it equally as fast as returning by reference, without the problem of dangling references. These optimizations are commonly called "Return Value Optimization (RVO)" and/or "Named Return Value Optimization (NRVO)".

Another way to for the caller to provide an empty vector (by reference), and have the function fill it in. Then it doesn't need to return anything.

You definitely should read this blog posting: Want Speed? Pass by value.

like image 63
Ben Voigt Avatar answered Sep 07 '25 07:09

Ben Voigt


By default, everything in C/C++ is passed by value, including return type, as in the example below:

T foo() ;

In C++, where the types are usually considered value-types (i.e. they behave like int or double types), the extra copy can be costly if the object's construction/destruction is not trivial.

With C++03

If you want to return by reference, or by pointer, you need to change the return type to either:

T & foo() ;  // return a reference
T * foo() ;  // return a pointer

but in both cases, you need to make sure the object returned still exists after the return. For example, if the object returned was allocated on stack in the body of the function, the object will be destroyed, and thus, its reference/pointer will be invalid.

If you can't guarantee the object still exists after the return, your only solution is to either:

  1. accept the cost of an extra copy, and hope for a Return Value Optimization
  2. pass instead a variable by reference as a parameter to the function, as in the following:

void foo(T & t) ;

This way, inside the function, you set the t value as necessary, and after the function returns, you have your result.

With C++11

Now, if you have the chance to work with C++0x/C++11, that is, with a compiler that supports r-values references/move semantics, if your object has the right constructor/operator (if your object comes from the standard library, then it's ok), then the extra temporary copy will be optimized away, and you can keep the notation:

T foo() ;

Knowing that the compiler will not generate an unnecessary temporary value.

like image 21
paercebal Avatar answered Sep 07 '25 06:09

paercebal