Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why would you pass an object by value in C++ [duplicate]

Possible Duplicate:
Is it better in C++ to pass by value or pass by constant reference?

I'm aware of the differences of passing by value, pointer and reference in C++, and I'd consider passing objects by value (instead of const reference) in C++ to be almost always a programming error.

void foo(Obj o); ... // Bad

void foo(const Obj &o); ... // Better

The only case I can think of where it might be appropriate to pass by value instead of const reference is where the object is smaller than a reference, and passing by value is therefore more efficient.

But, surely this is the sort of thing that compilers are built to determine?

Why does C++ actually need pass by value AND pass by const reference, and - are compilers allowed to automatically convert the call to (and from) a const reference if appropriate?

(There seem to be 100s of C++ calling convention question, asking about the differences between (say) value and reference - but I couldn't find one that asked "why?".)

like image 259
Roddy Avatar asked Aug 10 '12 15:08

Roddy


People also ask

Why is it usually better to pass objects by reference than by value?

The reason is simple: if you passed by value, a copy of the object had to be made and, except for very small objects, this is always more expensive than passing a reference.

What is an advantage of passing by value?

One of the advantages of pass-by-value is that a function is free to modify a parameter without inadvertently changing the data at the calling location. Another advantage is that the function argument may be any expression - not just a variable.

When should you use pass by value?

By definition, pass by value means you are making a copy in memory of the actual parameter's value that is passed in, a copy of the contents of the actual parameter. Use pass by value when when you are only "using" the parameter for some computation, not changing it for the client program.

Does pass by value make a copy?

pass-by-value makes a shallow-copy of the object. On the other side, pass-by-reference does not make any copy, it gets the reference of the object itself by just renaming it, so no any copying operation.


2 Answers

The question of when passing by value might be better than by const reference has different answers with different versions of the standard.

In the good old C++03, and a few years ago, the recommendation would be to pass anything that does not fit in a register by const reference. In this case, the answer would be:

  • Because Obj fits in a register and passing by value and passing by value will be more efficient

Still in C++03, in the last years (absurd as it seems some articles recommended this almost 10 years back, but there was no real consensus),

  • if the function needs to make a copy, then doing so in the interface allows the compiler to perform copy-elision if the source for the copy is a temporary, so it can be more efficient.

With the approval of the new C++11 standard, and increasing compiler support for rvalue-references, in many cases even when the copy cannot be elided, and again

  • if the function needs to make a copy, even when the copy cannot be elided, and for types that support it, the contents will be moved (in common jargon the object will be moved, but it is only the contents that get shifted), which again will be more efficient than copying internally.

As of the question of why the two different calling conventions, they have different goals. Passing by value allows the function to modify the state of the argument without interfering with the source object. Additionally, the state of the source object will not interfere with the function either (consider a multithreaded environment, and a thread modifying the source while the function is still executing).

like image 99
David Rodríguez - dribeas Avatar answered Nov 02 '22 23:11

David Rodríguez - dribeas


Certainly one reason C++ has pass-by-value is because it inherited it from C, and removing that could break code for little gain.

Secondly as you note, for types that are smaller than a reference passing by value would be less efficient.

Another less obvious case however is if you have a function that needs a copy of its argument for some reason:

void foo(const Obj& obj)
{
    if(very_rare_check()) return;

    Obj obj_copy(obj);
    obj_copy.do_work();
}

In this case note that you're forcing a copy. But suppose you call this function with the result of another function that returns by value:

Obj bar() { return Obj(parameters); }

And call it thusly: foo(bar());

Now when you use the const reference version, the compiler will end up making two objects: The temporary, and the copy in foo. If however you passed by value the compiler can optimize away all the temporaries to the location used by the by-value parameter of foo.

There's a great article about this and move semantics in general at http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

Finally the canonical way to implement certain operators is to use pass-by-value to avoid copies inside the operator:

Obj operator+(Obj left, const Obj& right)
{
    return left += right;
}

Note how this lets the compiler generate the copy in the parameter rather than forcing a copy or temporary object within the operator's code itself.

like image 41
Mark B Avatar answered Nov 03 '22 00:11

Mark B