3

In C++11 in a constructor, is it better to do:

class A
{
  A(std::string str) : mStr(std::move(str)) {}
  std::string mStr;  
}

or to do

class A
{
  A(const std::string& str) : mStr(str) {}
  std::string mStr;  
}

In which cases can copy elision occur when an rvalue is passed in to the constructor?

dan
  • 1,525
  • 1
  • 17
  • 35
  • A smart enough compiler can elide all of these if the argument passed in is not inspected again. That's the same rule as ever: the as-if rule. If your code can't tell the difference, the compiler can do it. – R. Martinho Fernandes Apr 14 '14 at 13:37
  • @R.MartinhoFernandes: I am not so sure here, the copy constructor of `std::string` has side effects (memory allocation), and copy elision is only allowed to ignore the possibility of side effects in a very narrow set of circumstances (which I believe only include returning from a function). – Matthieu M. Apr 14 '14 at 13:39
  • @MatthieuM. unless you override `new`, those side-effects are not observable. The as-if rule supersedes the copy elisions rules, because the as-if rule allows everything. – R. Martinho Fernandes Apr 14 '14 at 13:40
  • 1
    [Want speed? Pass by value.](http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/) It's not a universal rule of course, but it does answer your question - favouring pass-by-value + move. – Angew is no longer proud of SO Apr 14 '14 at 13:41
  • 2
    @MatthieuM. C++14 makes memory allocation optimizable. Specifically - from [N3936](https://github.com/cplusplus/draft/blob/master/papers/N3936.pdf) - 5.3.4/8 "A new-expression **may** obtain storage for the object by calling an allocation function (3.7.4.1).", and 5.3.4/10 "An implementation is allowed to omit a call to a replaceable global allocation function (18.6.1.1, 18.6.1.2)." – Casey Apr 14 '14 at 14:03
  • Related: [Is the pass-by-value-and-then-move construct a bad idiom?](http://stackoverflow.com/q/21035417/341970) or [When is overloading pass by reference (l-value and r-value) preferred to pass-by-value?](http://stackoverflow.com/q/18303287/341970) or [c++11 optimal parameter passing](http://stackoverflow.com/q/10472179/341970) or [Passing by value vs const & and && overloads](http://stackoverflow.com/q/14185985/341970) – Ali Apr 14 '14 at 14:11
  • @Casey: That's great, I know LLVM (at least) took the liberty already but it's great to see it official. Of course, it does not solve the issue of opaque copy constructors... – Matthieu M. Apr 14 '14 at 15:38

1 Answers1

1

You should do "pass by value and then move construct" if your type's move constructor is cheap, and use "Pass by reference and then copy construct" otherwise.

For lvalues

Pass by value and then move construct

You will be doing one copy followed by one move.

Pass by reference and then copy construct

You will be doing one copy

For Rvalues

Pass by value and then move construct

In the best case (when the rvalue is a temporary expression) you will be doing no copy/no move, followed by a move.

In the normal case (when the rvalue is not a temporary expression) you will be doing a move followed by another move.

Pass by reference and then copy construct

You will be doing one copy

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212