Paul
Paul

Reputation: 745

C++11 what happens when a function returns

I'm wondering what happens when I have a function like this:

typedef std::unordered_map<std::string,std::string> stringmap;

stringmap merge (stringmap a,stringmap b) 
{
  stringmap temp(a); temp.insert(b.begin(),b.end()); return temp;
}

what happens when the function returns?

Is 'temp' copied to a temporary r-value before being destroyed (out-of-scope) and with C++11 possibly NRVO-ptimized (so the copy of 'temp' is directly written to the return destination slot)?

Upvotes: 5

Views: 388

Answers (3)

Joseph Mansfield
Joseph Mansfield

Reputation: 110658

This would typically, without any special rules, result in a copy from temp to the return value of the function. However, there are two rules in the standard that aim to improve this. The first is that the copy may be elided (12.8/31):

in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object (other than a function or catch-clause parameter) with the same cvunqualified type as the function return type, the copy/move operation can be omitted by constructing the automatic object directly into the function’s return value

This is often known as named return value optimization (NRVO), a special case of return value optimization (RVO).

The second is that, since this situation meets the above criterion for copy elision, it will first be considered as a move (12.8/32):

When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue.

So the compiler will attempt the following steps:

  • Does the class have a move constructor?
    • If so, either move it or elide the move.
    • If not, does the class have a copy constructor?
      • If so, either move it or elide the copy.
      • If not, we can't copy or move this object.

Note that the class has to have either a move or copy constructor for this to work, even if the move or copy is elided.

Upvotes: 4

Mike Seymour
Mike Seymour

Reputation: 254461

Nothing should be copied. There are two possibilities:

  • temp is moved to an object in the caller's scope; or
  • the move is elided, and temp becomes an alias for an object in the caller's scope. This is known as "return value optimisation".

Before 2011 (specifically, without move semantics), the first case would require a copy rather than a move. The second case was allowed in C++98 as well as 11.

Upvotes: 7

bames53
bames53

Reputation: 88155

NRVO would mean that temp itself is constructed in the return value location. Without RVO, yes, temp is copied/moved from its location on the stack into the return value location prior to being destroyed.

Upvotes: 5

Related Questions