When should I declare my function as:
void foo(Widget w);
as opposed to:
void foo(Widget&& w);?
Assume this is the only overload (as in, I pick one or the other, not both, and no other overloads). No templates involved. Assume that the function foo requires ownership of the Widget (e.g. const Widget& is not part of this discussion). I'm not interested in any answer outside the scope of these circumstances. (See addendum at end of post for why these constraints are part of the question.)
The primary difference that my colleagues and I can come up with is that the rvalue reference parameter forces you to be explicit about copies. The caller is responsible for making an explicit copy and then passing it in with std::move when you want a copy. In the pass by value case, the cost of the copy is hidden:
//If foo is a pass by value function, calling + making a copy:
Widget x{};
foo(x); //Implicit copy
//Not shown: continues to use x locally
//If foo is a pass by rvalue reference function, calling + making a copy:
Widget x{};
//foo(x); //This would be a compiler error
auto copy = x; //Explicit copy
foo(std::move(copy));
//Not shown: continues to use x locally
Other than forcing people to be explicit about copying and changing how much syntactic sugar you get when calling the function, how else are these different? What do they say differently about the interface? Are they more or less efficient than one another?
Other things that my colleagues and I have already thought of:
The rvalue reference parameter means that you may move the argument, but does not mandate it. It is possible that the argument you passed in at the call site will be in its original state afterwards. It's also possible the function would eat/change the argument without ever calling a move constructor but assume that because it was an rvalue reference, the caller relinquished control. Pass by value, if you move into it, you must assume that a move happened; there's no choice.
Assuming no elisions, a single move constructor call is eliminated with pass by rvalue.
The compiler has better opportunity to elide copies/moves with pass by value. Can anyone substantiate this claim? Preferably with a link to gcc.godbolt.org showing optimized generated code from gcc/clang rather than a line in the standard. My attempt at showing this was probably not able to successfully isolate the behavior: https://godbolt.org/g/4yomtt
Addendum: why am I constraining this problem so much?
No overloads - if there were other overloads, this would devolve into a discussion of pass by value vs a set of overloads that include both const reference and rvalue reference, at which point the set of overloads is obviously more efficient and wins. This is well known, and therefore not interesting.
No templates - I'm not interested in how forwarding references fit into the picture. If you have a forwarding reference, you call std::forward anyway. The goal with a forwarding reference is to pass things as you received them. Copies aren't relevant because you just pass an lvalue instead. It's well known, and not interesting.
foo requires ownership of Widget (aka no const Widget&) - We're not talking about read-only functions. If the function was read-only or didn't need to own or extend the lifetime of the Widget, then the answer trivially becomes const Widget&, which again, is well known, and not interesting. I also refer you to why we don't want to talk about overloads.
What do rvalue usages say about an interface versus copying?
rvalue suggests to the caller that the function both wants to own the value and has no intention of letting the caller know of any changes it has made. Consider the following (I know you said no lvalue references in your example, but bear with me):
//Hello. I want my own local copy of your Widget that I will manipulate,
//but I don't want my changes to affect the one you have. I may or may not
//hold onto it for later, but that's none of your business.
void foo(Widget w);
//Hello. I want to take your Widget and play with it. It may be in a
//different state than when you gave it to me, but it'll still be yours
//when I'm finished. Trust me!
void foo(Widget& w);
//Hello. Can I see that Widget of yours? I don't want to mess with it;
//I just want to check something out on it. Read that one value from it,
//or observe what state it's in. I won't touch it and I won't keep it.
void foo(const Widget& w);
//Hello. Ooh, I like that Widget you have. You're not going to use it
//anymore, are you? Please just give it to me. Thank you! It's my
//responsibility now, so don't worry about it anymore, m'kay?
void foo(Widget&& w);
For another way of looking at it:
//Here, let me buy you a new car just like mine. I don't care if you wreck
//it or give it a new paint job; you have yours and I have mine.
void foo(Car c);
//Here are the keys to my car. I understand that it may come back...
//not quite the same... as I lent it to you, but I'm okay with that.
void foo(Car& c);
//Here are the keys to my car as long as you promise to not give it a
//paint job or anything like that
void foo(const Car& c);
//I don't need my car anymore, so I'm signing the title over to you now.
//Happy birthday!
void foo(Car&& c);
Now, if Widgets have to remain unique (as actual widgets in, say, GTK do) then the first option cannot work. The second, third and fourth options make sense, because there's still only one real representation of the data. Anyway, that's what those semantics say to me when I see them in code.
Now, as for efficiency: it depends. rvalue references can save a lot of time if Widget has a pointer to a data member whose pointed-to contents can be rather large (think an array). Since the caller used an rvalue, they're saying they don't care about what they're giving you anymore. So, if you want to move the caller's Widget's contents into your Widget, just take their pointer. No need to meticulously copy each element in the data structure their pointer points to. This can lead to pretty good improvements in speed (again, think arrays). But if the Widget class doesn't have any such thing, this benefit is nowhere to be seen.
Hopefully that gets at what you were asking; if not, I can perhaps expand/clarify things.
The rvalue reference parameter forces you to be explicit about copies.
Yes, pass-by-rvalue-reference got a point.
The rvalue reference parameter means that you may move the argument, but does not mandate it.
Yes, pass-by-value got a point.
But that also gives to pass-by-rvalue the opportunity to handle exception guarantee: if foo throws, widget value is not necessary consumed.
For move-only types (as std::unique_ptr), pass-by-value seems to be the norm (mostly for your second point, and first point is not applicable anyway).
EDIT: standard library contradicts my previous sentence, one of shared_ptr's constructor takes std::unique_ptr<T, D>&&.
For types which have both copy/move (as std::shared_ptr), we have the choice of the coherency with previous types or force to be explicit on copy.
Unless you want to guarantee there is no unwanted copy, I would use pass-by-value for coherency.
Unless you want guaranteed and/or immediate sink, I would use pass-by-rvalue.
For existing code base, I would keep consistency.
Unless the type is a move-only type you normally have an option to pass by reference-to-const and it seems arbitrary to make it "not part of the discussion" but I will try.
I think the choice partly depends on what foo is going to do with the parameter.
The function needs a local copy
Let's say Widget is an iterator and you want to implement your own std::next function. next needs its own copy to advance and then return. In this case your choice is something like:
Widget next(Widget it, int n = 1){
std::advance(it, n);
return it;
}
vs
Widget next(Widget&& it, int n = 1){
std::advance(it, n);
return std::move(it);
}
I think by-value is better here. From the signature you can see it is taking a copy. If the caller wants to avoid a copy they can do a std::move and guarantee the variable is moved from but they can still pass lvalues if they want to.
With pass-by-rvalue-reference the caller cannot guarantee that the variable has been moved from.
Move-assignment to a copy
Let's say you have a class WidgetHolder:
class WidgetHolder {
Widget widget;
//...
};
and you need to implement a setWidget member function. I'm going to assume you already have an overload that takes a reference-to-const:
WidgetHolder::setWidget(const Widget& w) {
widget = w;
}
but after measuring performance you decide you need to optimize for r-values. You have a choice between replacing it with:
WidgetHolder::setWidget(Widget w) {
widget = std::move(w);
}
Or overloading with:
WidgetHolder::setWidget(Widget&& widget) {
widget = std::move(w);
}
This one is a little bit more tricky. It is tempting choose pass-by-value because it accepts both rvalues and lvalues so you don't need two overloads. However it is unconditionally taking a copy so you can't take advantage of any existing capacity in the member variable. The pass by reference-to-const and pass by r-value reference overloads use assignment without taking a copy which might be faster
Move-construct a copy
Now lets say you are writing the constructor for WidgetHolder and as before you have already implemented a constructor that takes an reference-to-const:
WidgetHolder::WidgetHolder(const Widget& w) : widget(w) {
}
and as before you have measured peformance and decided you need to optimize for rvalues. You have a choice between replacing it with:
WidgetHolder::WidgetHolder(Widget w) : widget(std::move(w)) {
}
Or overloading with:
WidgetHolder::WidgetHolder(Widget&& w) : widget(std:move(w)) {
}
In this case, the member variable cannot have any existing capacity since this is the constructor. You are move-constucting a copy. Also, constructors often take many parameters so it can be quite a pain to write all the different permutations of overloads to optimize for r-value references. So in this case it is a good idea to use pass-by-value, especially if the constructor takes many such parameters.
Passing unique_ptr
With unique_ptr the efficiency concerns are less important given that a move is so cheap and it doesn't have any capacity. More important is expressiveness and correctness. There is a good discussion of how to pass unique_ptr here.
When you pass by rvalue reference object lifetimes get complicated. If the callee does not move out of the argument, the destruction of the argument is delayed. I think this is interesting in two cases.
First, you have an RAII class
void fn(RAII &&);
RAII x{underlying_resource};
fn(std::move(x));
// later in the code
RAII y{underlying_resource};
When initializing y, the resource could still be held by x if fn doesn't move out of the rvalue reference. In the pass by value code, we know that x gets moved out of, and fn releases x. This is probably a case where you would want to pass by value, and the copy constructor would likely be deleted, so you wouldn't have to worry about accidental copies.
Second, if the argument is a large object and the function doesn't move out, the lifetime of the vectors data is larger than in the case of pass by value.
vector<B> fn1(vector<A> &&x);
vector<C> fn2(vector<B> &&x);
vector<A> va; // large vector
vector<B> vb = fn1(std::move(va));
vector<C> vc = fn2(std::move(vb));
In the example above, if fn1 and fn2 don't move out of x, then you will end up with all of the data in all of the vectors still alive. If you instead pass by value, only the last vector's data will still be alive (assuming vectors move constructor clears the sources vector).
One issue not mentioned in the other answers is the idea of exception-safety.
In general, if the function throws an exception, we would ideally like to have the strong exception guarantee, meaning that the call has no effect other than raising the exception. If pass-by-value uses the move constructor, then such an effect is essentially unavoidable. So an rvalue-reference argument may be superior in some cases. (Of course, there are various cases where the strong exception guarantee isn't achievable either way, as well as various cases where the no-throw guarantee is available either way. So this is not relevant in 100% of cases. But it's relevant sometimes.)
Choosing between by-value and by-rvalue-ref, with no other overloads, is not meaningful.
With pass by value the actual argument can be an lvalue expression.
With pass by rvalue-ref the actual argument must be an rvalue.
If the function is storing a copy of the argument, then a sensible choice is between pass-by-value, and a set of overloads with pass-by-ref-to-const and pass-by-rvalue-ref. For an rvalue expression as actual argument the set of overloads can avoid one move. It's an engineering gut-feeling decision whether the micro-optimization is worth the added complexity and typing.
One notable difference is that if you move to an pass-by-value function:
void foo(Widget w);
foo(std::move(copy));
compiler must generate a move-constructor call Widget(Widget&&) to create the value object. In case of pass-by-rvalue-reference no such call is needed as the rvalue-reference is passed directly to the method. Usually this does not matter, as move constructors are trivial (or default) and are inlined most of the time.
(you can check it on gcc.godbolt.org -- in your example declare move constructor Widget(Widget&&); and it will show up in assembly)
So my rule of thumb is this:
if the object represents a unique resource (without copy semantics) I prefer to use pass-by-rvalue-reference,
otherwise if it logically makes sense to either move or copy the object, I use pass-by-value.
Related
I got a dispute with my colleague.
We have following example:
class Key
{
public:
Key() {}
Key(Key&& ) {}
Key(const Key& ) {}
};
class KeyWrapper
{
public:
KeyWrapper(const Key& key) : _key(key) {}
private:
Key _key;
};
int main()
{
Key key;
KeyWrapper wrapper(std::move(key));
return 0;
}
My point that in line KeyWrapper wrapper(std::move(key)); std::move has no effect, because KeyWrapper constructor accepts const ref and therefore std::move can be omitted. And inside of this constructor we can't write _key(std::move(key)), because we have constant reference to input parameter.
But my colleague says that std::move() should be in line KeyWrapper wrapper(std::move(key)); and also we should write _key(std::move(key)).
Please, judge us...
Here's my take.
If logically a move is the proper thing to do at the call site (in this case main()), you should move it. If the code receiving the object does not handle moves, reverting to c++98-style copies, that's a valid implementation of a move (but not optimized.) There is still no problem. Down the road, if the object begins accepting rvalue references or gains a forwarding-ref interface, you will benefit from the move improvements without having to go back and fix your calling code to take advantage of the change.
However, in a function receiving key as a const &, it should never move its argument. There is no justification for this, because you do not know anything about the caller, and cannot assume it is a safe thing to do.
Some classes are "safe to use after move" because move does not actually modify the source object, however, relying on this is really a bad idea as it depends on implementation details that are subject to change without warning, and is really just doing it wrong.
Here's some guidelines for when to move or not:
If a function receives an lvalue reference, it must never move it
If a function receives an object by value, it is safe to move
If a function receives an rvalue reference, it is safe to move
If a function receives a "forwarding reference" (a template function taking T&&) then it is not safe to move, but is safe to forward.
Notice, the rules above do not change based on knowledge that the underlying type is known to have identical behavior when moved and copied. For example, a trivial class containing only primitive data is technically safe to move even from a const& because moving it doesn't modify the source. However, do not do that because it has no benefit and is depending on something you might not control (or realize has changed.) It also make it look as though you are confused about move semantics, and will cause people to doubt the robustness of the rest of the design.
If you are in a controlled environment where you intimately know the caller and callee code are working together, and they are private without outside code using them, you may feel safe to relax some of these rules--but I still do not recommend it because it's harder to reason about when your code does odd things that break convention, and there is still little/no benefit.
According to the core guidelines:
F.18: For “will-move-from” parameters, pass by X&& and std::move the parameter
The example is:
void sink(vector<int>&& v) { // sink takes ownership of whatever the argument owned
// usually there might be const accesses of v here
store_somewhere(std::move(v));
// usually no more use of v here; it is moved-from
}
I noticed that I tend to use smart pointers for all objects except cheaply-copied (which I almost always consider only primitives). So I almost always use the following guidelines:
void sink(std::unique_ptr<OtherThanPrimitive> p) {
// use p ... possibly std::move(p) onward somewhere else
} // p gets destroyed
I started to consider if I use best practice. What I can think of as advantage of the first approach is forcing caller of a function to explicitly std::move and it makes code cleaner. In the second approach move constructor will be called two times, but for smart pointer it's not a big cost. Considering above I started to think about changing my habit to use the first approach always for collections that I am sure that support moving (so most of STL collections). Second approach for custom objects (I assume that cost of considering writing custom move constructor for a class outstrips the profit of readability). Is there any best practice that covers that? What approach do you usually apply? Am I missing something in my justification?
What I can think of as advantage of the first approach is forcing caller of a function to explicitly std::move and it makes code cleaner. In the second approach move constructor will be called two times, but for smart pointer it's not a big cost.
Between void sink(T&&) and void sink(T): both require std::move for move-only types or to invoke the move constructor. The second form can also copy, given a copyable lvalue argument. If T is not cheap to copy, silently getting a copy can be a disadvantage. The second form, even when used with a move-only type, will have an extra move, into the function parameter, compared to the first approach. If T is not cheap to move, that can be a disadvantage. When moving into a data member, or otherwise logically making a copy of the argument, the second form allows one overload accepting both T&& and const T& arguments, instead of having one overload for each, and then 2^N overloads for N arguments.
However, the second form unconditionally moves from the argument. The first may conditionally move from the argument or not move from the argument at all. The caller cannot tell (bad!). The second form provides a clearer expression of intent.
Note that issue 526 has a nice little helper function copy which you could use with the first form for not so cheaply copyable types, to make a copy explicit. With that helper, you can move by default, with the minimum number of moves, and opt in to an explicit copy. The signature still provides less clarity of intent than the second form.
Considering above I started to think about changing my habit to use the first approach always for collections that I am sure that support moving (so most of STL collections). Second approach for custom objects
I don't think custom objects versus move-supporting collections is the right distinction. If T is not movable, the parameter should be const T& or T (if you want a copy). Using the first form in that case does not make sense.
If T is movable, as a rule of thumb, use the core guidelines. Use the first form. If T is cheaply movable, use the second form.
I assume that cost of considering writing custom move constructor for a class outstrips the profit of readability
One shouldn't need to write custom move constructors for most classes. Something owns the storage. That needs a custom move constructor. Internal bookkeeping that point into the storage generate the need for a custom move constructor. So, containers. And if you're writing a container for general use with supplied types, one should probably write a move constructor if it could be more efficient. Doing otherwise might be more surprising.
void foo(T, size_t size)(in T[size] data){...}
//vs
void foo(T, size_t size)(const ref T[size] data){...}
According to https://stackoverflow.com/a/271344/944430 it seems that in C++ pass by value can be faster in some situations.
But D has a special keyword in and I am wondering when I should use it. Does in always result in a copy or is it a compiler optimization?
Are there any guidelines that I can follow that help me decide between const ref and in?
I would argue that you should never use in on function parameters. in is an artifact from D1 that was kept to reduced code breakage but was changed to be equivalent to const scope. So, every time you think of typing in on a function parameter, think of const scope, since that's what you're really doing. And scope currently only does anything with delegates, in which case, it's telling the compiler that the function taking the delegate is not going to return it or assign it to anything and that therefore no closure has to be allocated to hold the state of that delegate (so, it improves efficiency in many cases for delegates), whereas for all other types, it's completely ignored, which means that using it is meaningless (and potentially confusing), and if it ever does come to mean something else for other types (e.g. it's been suggested that it should enforce that a pointer that's passed in as scope can't escape the function), then the semantics of your code could change in unexpected ways. Presumably, it'll be accompanied by the appropriate warnings when the happens, but why mark your code with a meaningless attribute that could have meaning later and thus force you to change your code? At this point, scope should only be used on delegates, so in should only be used on delegates, and you don't usually want const delegates. So, just don't use in.
So, ultimately, what you're really asking is whether you should use const or const ref.
The short answer is that you generally shouldn't use ref unless you want to mutate the argument you're passing in. I would also point out that this question is meaningless for anything but structs and maybe static arrays, because classes are already reference types, and none of the built-in types (save for static arrays) cost much of anything to copy. The longer answer is...
Move semantics are built into D, so if you have a function that takes its argument by value - e.g.
auto foo(Bar bar) { ... }
then it will move the argument if it can. If you pass it an lvalue (a value that can be on the left-hand side of an assignment), then that value is going to be copied except maybe in circumstances where the compiler is able to determine that it can optimize the copy away (e.g. when the variable is never used after that function call), but that's going to depend on the compiler and compiler flags used. So, passing a variable to a function by value will usually result in a copy. However, if you pass the function an rvalue (the values that can't go on the left-hand side of an assignment), then it will move that object rather than copying it. This is different from C++, where move semantics were not introduced until C++11, and even then, they require move constructors, whereas D uses postlbit constructors, which changes it so that moves can be done by default. A couple of previous SO questions on that:
Does D have something akin to C++0x's move semantics?
Questions about postblit and move semantics
So, yes, there are cases in D where passing by ref would avoid a copy, but in D, ref always requires an lvalue (even with const). So, if you start putting ref const(T) everywhere like you'd do const T& in C++, you're going to have a lot of functions which are really annoying to call, because every temporary will have to be assigned to a variable first to call the function. So, you should seriously consider only ever using ref for when you want to mutate a variable that's passed in and not for efficiency. Certainly, your default should be to not pass by const ref, but if you do need that extra efficiency, you have two options:
Overload the function on ref-ness so that you have an overload that takes by const ref and one that takes by ref so that the lvalues get passed to one without being copied, and the rvalues get passed to the other without needing an extraneous variable. e.g.
auto foo(const Bar bar) { foo(bar); }
auto foo(ref const(Bar) bar) { ... }
And that's a bit annoying but works well enough when you only have one parameter with ref. However, you get a combinatorial explosion of overloads as more ref parameters are added. e.g.
auto foo(const Bar bar, const Glop glop) { foo(bar, glop); }
auto foo(ref const(Bar) bar, const Glop glop) { foo(bar, glop); }
auto foo(const Bar bar, ref const(Glop) glop) { foo(bar, glop); }
auto foo(ref const(Bar) bar, ref const(Glop) glop) { ... }
So, that works to a point, but it's not particularly pleasant. And if you define the overloads like I did here, then it also has the downside that the rvalues end up being passed to a wrapper function (adding an extra function call - though one that should be quite inlinable), which means that they're now passed by ref to the main overload and if one of those parameters is passed to another function or returned, the compiler can't do a move, whereas if ref hadn't been involved, then it could have. That's one of the reasons that it's now argued that you shouldn't use const T& heavily in C++11 like you would have done in C++98.
You can get around that problem by duplicating the function body for each overload, but that obviously creates a maintenance problem as well as creating code bloat.
The alternative is to use auto ref, which basically does that for you, but the function has to be templated. e.g.
auto foo()(const auto ref Bar bar, const auto ref Glop glop) { ... }
So, now you only have one overload, but it still generates all of those overloads with the full code underneath the hood every time the template is instantiated with a different combination of ref-ness. So, your code is cleaner, but you still get more bloat, and if you need to do this with a virtual function, then you're out of luck and have to go back to the more explicit overload solution, because templated functions can't be virtual.
So, in general, trying to have your functions accept const ref for efficiency reasons just gets ugly. The fact that D has move semantics built in reduces the need for it (just like with C++11, it's now argued that passing by value is often better, thanks to move semantics and how the compiler optimizes them). And it's ugly enough to do in D in the general case that unless you actually get a performance boost that matters, it's probably not worth passing by ref just for efficiency. You should probably avoid using ref for efficiency unless you've actually measured a difference in performance that's worth the pain.
The other thing to consider - separate from ref-ness - is that D's const is a lot more restrictive than C++'s const (e.g. casting away const and mutating is undefined behavior in D, and D's const is transitive). So, slapping const all over the place can sometimes become problematic - especially in generic code. So, using it can be great for preventing accidental mutation or indicating that a function does not mutate its arguments, but don't just blithely slap it everywhere that shouldn't be mutating the variable like you would in C++. Use it where it makes sense, but be aware that you will run into cases where D's const is too restrictive to be usable, even if C++'s const would have worked.
So, in most cases, when you want your function to take a T, you should default to it taking a plain T. And then if you know that efficiency is a concern, you can consider using some form of ref (probably favoring auto ref or const auto ref if you're not dealing with a virtual function). But default to not using ref. Your life will be much more pleasant that way.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is move semantics?
I recently attended a C++11 seminar and the following tidbit of advice was given.
when you have && and you are unsure, you will almost always use std::move
Could any one explain to me why you should use std::move as opposed to some alternatives and some cases when you should not use std::move?
First, there's probably a misconception in the question I'll address:
Whenever you see T&& t in code (And T is an actual type, not a template type), keep in mind the value category of t is an lvalue(reference), not an rvalue(temporary) anymore. It's very confusing. The T&& merely means that t is constructed from an object that was an rvalue 1, but t itself is an lvalue, not an rvalue. If it has a name (in this case, t) then it's an lvalue and won't automatically move, but if it has no name (the result of 3+4) then it is an rvalue and will automatically move into it's result if it can. The type (in this case T&&) has almost nothing to do with the value category of the variable (in this case, an lvalue).
That being said, if you have T&& t written in your code, that means you have a reference to a variable that was a temporary, and it is ok to destroy if you want to. If you need to access the variable multiple times, you do not want to std::move from it, or else it would lose it's value. But the last time you acccess t it is safe to std::move it's value to another T if you wish. (And 95% of the time, that's what you want to do). All of this also applies to auto&& variables.
1. if T is a template type, T&& is a forwarding reference instead, in which case you use std::forward<T>(t) instead of std::move(t) the last time. See this question.
I found this article to be pretty enlightening on the subject of rvalue references in general. He mentions std::move towards the end. This is probably the most relevant quote:
We need to use std::move, from <utility> -- std::move is a way of
saying, "ok, honest to God I know I have an lvalue, but I want it to
be an rvalue." std::move does not, in and of itself, move anything; it
just turns an lvalue into an rvalue, so that you can invoke the move
constructor.
Say you have a move constructor that looks like this:
MyClass::MyClass(MyClass&& other): myMember(other.myMember)
{
// Whatever else.
}
When you use the statement other.myMember, the value that's returned is an lvalue. Thus the code uses the copy constructor to initialize this->myMember. But since this is a move constructor, we know that other is a temporary object, and therefore so are its members. So we really want to use the more-efficient move constructor to initialize this->myMember. Using std::move makes sure that the compiler treats other.myMember like an rvalue reference and calls the move constructor, as you'd want it to:
MyClass::MyClass(MyClass&& other): myMember(std::move(other.myMember))
{
// Whatever else.
}
Just don't use std::move on objects you need to keep around - move constructors are pretty much guaranteed to muck up any objects passed into them. That's why they're only used with temporaries.
Hope that helps!
When you have an object of type T&&, a rvalue, it means that this object is safe to be moved, as no one else will depend on its internal state later.
As moving should never be more expensive than copying, you will almost always want to move it. And to move it, you have to use the std::move function.
When should you avoid std::move, even if it would be safe? I wouldn't use it in trivial examples, e.g.,:
int x = 0;
int y = std::move(x);
Beside that, I see no downsides. If it does not complicate the code, moving should be done whenever possible IMHO.
Another example, where you don't want to move are return values. The language guarantees that return values are (at least) moved, so you should not write
return std::move(x); // not recommended
(If you are lucky, return value optimization hits, which is even better than a move operation.)
You can use move when you need to "transfer" the content of an object somewhere else, without doing a copy. It's also possible for an object to take the content of a temporary object without doing a copy, with std::move.
Read more on Rvalue references and move constructors from wikipedia.
This question already has answers here:
Closed 10 years ago.
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?".)
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).
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.
If I wanted to do things to the object within the function without affecting the original, I would pass by value:
A minus(A b){
b.val=-b.val;
return b;
}
The copy swap idiom uses passe by value to achieve a compiler generated copy.
MyClass& operator=(MyClass value) // pass by value to generate copy
{
value.swap(*this); // Now do the swap part.
return *this;
}
Basically in situations where you will need to modify the parameter but do not want to touch the original. In these situations if you pass by const reference you manually need to create a copy inside the function. This manual steps will prevent certain optimizations that the compiler can perform if you let the compiler handle the copy.
MyClass a;
// Some code
a = MyClass(); // reset the value of a
// compiler can easily elide this copy.
If the object is mutable, passing by value gives the receiver its own copy to use and where sensible change, without affecting the caller's copy - always assuming it's a sufficiently deep copy.
This may simplify thinking in some multi-threaded situations.
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?
Let me answer the second one first: sometimes.
Compilers are allowed to elide the copy into the parameter, but only if you pass in an rvalue temporary. For example:
void foo(Obj o);
foo((Obj()))); //Extra set of parenthesis are needed to prevent Most Vexing Parse
The copying of the temporary into the argument parameter may be elided (ie: not copied), at the compiler's convenience).
However, this copy will never be elided:
Obj a;
foo(a);
Now, on to the first. C++ needs both because you may want to use both for different things. Pass by value is useful for transferring ownership; this is more important in C++11 where we can move rather than copy objects.