Quick Q: Why does this function take a parameter by value? -- StackOverflow

A classic on SO:

Why do we copy then move?

I saw code somewhere in which someone decided to copy an object and subsequently move it to a data member of a class. This left me in confusion in that I thought the whole point of moving was to avoid copying. Here is the example:

struct S
{
    S(std::string str) : data(std::move(str))
    {}
};

Here are my questions:

  • Why aren't we taking an rvalue-reference to str?
  • Won't a copy be expensive, especially given something like std::string?
  • What would be the reason for the author to decide to make a copy then a move?
  • When should I do this myself?

Add a Comment

Comments are closed.

Comments (4)

1 0

Sektor said on Apr 16, 2014 07:12 AM:

This is a very important question, and the answer explains the very important parts of move semantics. Despite that it's there quite a long time, it will still take a long time until anyone will be really using it.

It also emphasizes one important thing: You can now forget using everywhere this clumsy "const T&" whenever you want to pass a value of a "possibly large object treated as a value" to a function. Just use "T", it's simpler.
0 0

Bjarne Stroustrup said on Apr 16, 2014 06:05 PM:

It is too early to write off "const T&". Most uses of "const T&" does not lead to a copy of T. The rule I use outside very specialized implementation details is: avoid explicit move(). It is rarely needed.
0 0

Denton Cockburn said on Apr 17, 2014 05:58 PM:

Bjarne, can you elaborate on that rule a bit?

Dave Abrahams' "Pass by value" article started quite a movement to using copy then move. You're the first I've seen to push back. Considering your position, a lot could be learnt from your point of view.
0 0

Bjarne Stroustrup said on Apr 17, 2014 07:06 PM:

I'm less quick to formulate firm rules than some. For example, I'm still trying to understand all the implications of taking T&& arguments.

move(x) leaves a moved-from object behind. That's a trap for the unwary. In ordinary programming, I see little reason to open that can of worms.

If you pass-by-const-reference, you leave it up to the callee whether to copy or not. By using pass-by-value, you force the caller to decide whether to pass a copy or move and object. The latter could leave a moved-from object behind.

I have little doubt that code "littered with explicit move()s" will be as brittle and hard to get right as code "littered with casts" (after all move() is a slightly disguised cast) or "littered with news and deletes."

Obviously, one might try to address my concerns with rules for how and when to use explicit move(), but that just provides yet-another level of rules and complexity.

I do discuss argument passing in TC++PL4