WhatABeautifulWorld
WhatABeautifulWorld

Reputation: 3388

Will this do default move operation

I have a function foo:

std::vector<T> foo() {
  std::vector<T> result;
  // populate result
  {
    /*
       for loop with result.push_back().
       ignore real code.
    */
  }
  //
  return result;    <-- note there without std::move
}

Will it do extra copy if I assign like the following?

const auto v = foo();   <-- will it move the vector by default?
const auto &v = foo();  <-- same question as above, assuming T is movable

I am in particular interested in the second case as for the first case it's very likely the compiler knows to move the result from foo() to v.

const auto &v = foo();

For this case, the foo() function creates a temp result. Now as v is a reference, it can't move result to v. Thus it needs to create a new copy. Is my understanding right?

Upvotes: 3

Views: 122

Answers (2)

badola
badola

Reputation: 870

The compilers are permitted to any and all code transformations that do not change the observable behavior of the program, by applying the as-if rule.

However, copy_elision is an exception from the as-if rule: the compiler may remove calls to move- and copy-constructors and the matching calls to the destructors of temporary objects even if those calls have observable side effects. To witness these side effects, you have to use -fno-elide-constructors option while compiling.

From the copy_elision page, we should look at the clause:

In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type. This variant of copy elision is known as NRVO, "named return value optimization".

When the compiler sees the below structure, it knows it is a candidate for NRVO.

T FunctionName ( ... )
{
    T a;
    ...
    return a;
}

Which matches the code structure of your problem.

std::vector<T> foo() {
  std::vector<T> result;
  // populate result
  {
    /*
       for loop with result.push_back().
       ignore real code.
    */
  }
  return result;
}

Case 1 -

const auto v = foo();   <-- will it move the vector by default?

What you are witnessing is not move-semantics, it is just NRVO.
So the question doesn't have any relevance here.

Case 2 -

const auto &v = foo();  <-- same question as above, assuming T is movable

It doesn't matter if T is movable. There is no move happening here.
The concept that is taking place is const & can bind to a temporary.

We would achieve the same result in pre-C++11 compiler as well, which didn't have move-semantics support.

Upvotes: 3

WhatABeautifulWorld
WhatABeautifulWorld

Reputation: 3388

For both cases, it seems there's no extra copy, seen from this link

Upvotes: 0

Related Questions