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.
Related
Item 29 from Effective Modern C++, Scott Meyers lists three scenarios where move semantics don't improve code's performance,
[…] move semantics do you no good:
No move operations: The object to be moved from fails to offer move operations […]
Move not faster: […] move operations that are no faster than its copy operations.
Move not usable: The context […] requires a move operation that emits no exceptions, but that operation isn't declared noexcept.
which are all clearly explained in the preceding pages, and then adds another one
[…] another scenario where move semantics offers no efficiency gain:
Source object is lvalue: With very few exceptions (see e.g. Item 25) only rvalues may be used as the source of a move operation.
(Item 25 is titled Use std::move on rvalue references and std::forward on universal references, but I don't see how it is related to the bullet point that cross-references it.)
After this, the text essentially goes back to summarizing the item, with no further reference to that fourth bullet point.
What does that bullet point refer to?
As far as I understand move semantics, even if I want to move from an lvalue, say x, I still need to cast it to an rvalue via std::move(x) (or an equivalent static_cast), so I'm technically still moving from an rvalue (specifically an xvalue in this case), not an lvalue.
So I'd be tempted to say that an lvalue cannot be the source object of a move operation.
What am I missing about this topic?
The term lvalue refers to somehow “named” values, i.e., entities having multiple references. Move semantics don’t really apply to them as you shouldn’t “steal” the representation of something which may be referred to elsewhere. That is, if the source object is an lvalue you simply never move! So, move construction doesn’t provide a benefit here. In fact, lvalues don’t bind willingly to rvalue references - you’d beed to force that binding, e.g., by using std::move().
Essentially, your point is entirely correct: an lvalue cannot be the source of a move operation - and hence move operations don’t provide a benefit where lvalues are involved.
As an example: You have a class T with a move constructor. You have a function returning an object of type T, and you try to make it faster by returning in r-value. Now if you start with
T x;
x.a = ...;
x.b = ...;
x.c = ...;
return x;
then an object x will be constructed, a new unnamed object will be created by the return statement, then x is destructed, then the return value is moved. And eventually the caller will call the destructor for the moved result. So you have two constructors, two destructors, no savings.
If you start with
T x(a, b, c);
return x;
then you have the same problem, two constructors and destructors, no savings. To actually save anything, you need to write
return T(a, b, c);
or return the return value of another function returning an object.
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.
As I read some articles, rvalue references and move semantics are usually described together. However as I understand, rvalue references are just references to rvalues and have nothing to do on their own with move semantics. And move semantics could be implemented probably without even using rvalue references. So the question is, why move constructor/operator= use rvalue references? Was it just to make it easier to write the code?
Consider the problem. There are two basic move operations we want to support: move "construction" and move "assignment". I use quotations there because we don't necessarily have to implement them with constructors or move assignment operators; we could use something else.
Move "construction" means creating a new object by transferring the contents from an existing object, such that deleting the old object doesn't deallocate resources now used in the new one. Move "assignment" means taking a pre-existing object and transferring the contents from an existing object, such that deleting the old object doesn't deallocate resources now used in the new one.
OK, so these are the operations we want to do. Well, how to do it?
Take move "construction". While we don't have to implement this with a constructor call, we really want to. We don't want to force people to do two-stage move construction, even if it's behind some magical function call. So we want to be able to implement movement as a constructor. OK, fine.
Here's problem 1: constructors have no names. Therefore, you can only differentiate them based on argument types and overloading resolution. And we know that the move constructor for an object of type T must take an object of type T as a parameter. And since it only needs one argument, it therefore looks exactly like a copy constructor.
OK, so now we need some way to satisfy overloading. We could introduce some standard library type, a std::move_ref. It would be like std::reference_wrapper, but it would be a distinct type. Therefore, you could say that a move constructor is a constructor that takes a std::move_ref<T>. Alright, fine: problem solved.
Only not; we now have new problems. Consider this code:
std::string MakeAString() { return std::string("foo"); }
std::string data = MakeAString();
Ignoring elision, C++11's expression value category rules state that a type which is returned from a function by value is an prvalue. And therefore, it will automatically be used by move constructors/assignment operators wherever possible. No need for std::move or the like.
To do it your way would require this:
std::string MakeAString() { return std::move(std::string("foo")); }
std::string data = std::move(MakeAString());
Both of those std::move calls would be needed to avoid copying. You have to move out of the temporary and into the return value, and then move out of the return value and into data (again, ignoring elision).
If you think that this is merely a minor annoyance, consider what else rvalue references buy us: perfect forwarding. Without the special reference-collapsing rules, you could not write a proper forwarding function that forwards copy and move semantics perfectly. std::move_ref would be a real C++ type; you couldn't just slap arbitrary rules like reference collapsing onto it like you can with rvalue references.
At the end of the day, you need some kind of language construct in place, not merely a library type. By making it a new kind of reference, you get to be able to define new rules for what can bind to that reference (and what cannot). And you get to define special reference-collapsing rules that make perfect forwarding possible.
The connection is that it is safe to move from an rvalue (because (in the absence of casts) rvalues refer to objects that are at the end of their lifespans), so a constructor that takes an rvalue reference can be safely implemented by pilfering/moving from the referenced object.
From a C++-language point of view, this is the end of the connection, but the standard library further expands on this connection by consistently making construction from lvalues copy and construction from rvalues move, and by providing helper functions (such as std::move) which make it straightforward to chose whether to move or copy a particular object (by changing around the value category of the object in the expression that causes the copy/move).
Move semantics can be implemented without rvalue-references, but it would be a lot less neat. A number of problems would need to be solved:
How to capture an rvalue by non-const reference?
How to distinguish between a constructor that copies and a constructor that moves?
How to ensure that moves are used wherever they would be a safe optimization?
How to write generic code that works with both movable and copyable objects?
In C++11, value parameters (and other values) enjoy implicit move when returned:
A func(A a) {
return a; // uses A::A(A&&) if it exists
}
At least in MSVC 2010, rvalue reference parameters need std::move:
A func(A && a) {
return a; // uses A::A(A const&) even if A::A(A&&) exists
}
I would imagine that inside functions, an rvalue reference and a value behave similar, with the only difference that in case of values, the function itself is responsible for destruction, while for rvalue references, the responsibility is outside.
What is the motivation for treating them differently in the standard?
The standardization committee expended great effort in creating wording so that moves would only ever happen in exactly two circumstances:
When it is clearly safe to do so.
When the user explicitly asks (via std::move or a similar cast).
A value parameter will unquestionably be destroyed at the end of the function. Therefore, returning it by move is clearly safe; it can't be touched by other code after the return (not unless you're deliberately trying to break things, in which case you probably triggered undefined behavior). Therefore, it can be moved from in the return.
A && variable could be referring to a temporary. But it could be referring to an lvalue (a named variable). It is therefore not clearly safe to move from it; the original variable could be lurking around. And since you didn't explicitly ask to move from it (ie: you didn't call std::move in this function), no movement can take place.
The only time a && variable will be implicitly moved from (ie: without std::move) is when you return it. std::move<T> returns a T&&. It is legal for that return value to invoke the move constructor, because it is a return value.
Now it is very difficult to call A func(A &&a) with an lvalue without calling std::move (or an equivalent cast). So technically, it should be fine for parameters of && type to be implicitly moved from. But the standards committee wanted moves to be explicit for && types, just to make sure that movement didn't implicitly happen within the scope of this function. That is, it can't use outside-of-function knowledge about where the && comes from.
In general, you should only take parameters by && in two cases: either you're writing a move constructor (or move assignment operator, but even that can be done by value), or you're writing a forwarding function. There may be a few other cases, but you shouldn't take && to a type unless you have something special in mind. If A is a moveable type, then just take it by value.
This was fixed for C++20 by P0527 and P1825. The only way to have a function parameter bind to an rvalue reference is for the source to either be a temporary or for the caller to explicitly cast a non-temporary to an rvalue (for instance, with std::move). Therefore, this "mandatory optimization" was deemed safe.
In your first case, the compiler knows that a is going away and nothing will be able to cling on to it: clearly, this object can be moved from and if it is not it will be destroyed. In the second case, the rvalue reference indicates that it is permissible to move from the object and the caller doesn't expect the object to stay around. However, it is the function's choice whether it takes advantage of this permission or not and there may be reasons why the function sometimes wants to move from the argument and sometimes it doesn't want to. If the compiler were given the liberty to move off this object, there would be no way to prevent the compiler from doing so. However, using std::move(a) there is already a way to indicate that it is desired to move from the object.
The general rule in the standard is that the compiler only ever moves objects implicitly which are known to go away. When an rvalue reference comes in, the compiler doesn't really know that the object is about to away: if it was explicitly std::move()ed it actually stays around.
Prior to C++11, and as a standard programming idiom, temporaries are often assigned to variables to make the code cleaner. For small types a copy is typically made, and for larger types perhaps a reference, such as:
int a = int_func();
T const & obj = obj_func();
some_func( a, obj );
Now, compare this to the inlined form:
some_func( int_func(), obj_func() );
Prior to C++11 this had nearly identical semantic meaning. With the introduction of rvalue-reference and move semantics the above are now entirely different. In particular, by forcing obj to type T const & you have removed the ability to use a move constructor, whereas the inline form the type can be a T&& instead.
Given that the first is a common paradigm, is there anything in the standard that would allow an optimizer to use a move constructor in the first case? That is, could somehow the compiler ignore the binding to a T const & and instead treat it as a T&&, or, as I suspect, would this violate the rules of the abstract machine?
Second part of the question, to do this correctly in C++11 (without eliminating named temporaries) we need to somehow declare a proper rvalue-reference. We can also use the auto keyword. So, what is the proper way to do this? My guess is:
auto&& obj = obj_func();
Part 1:
The compiler is not allowed to implicilty transform obj into a non-const rvalue and thus use a move constructor when calling some_func.
Part 2:
auto&& obj = obj_func();
This will create a non-const reference to the temporary, but it will not be implicitly moved from when calling some_func because obj is an lvalue. To transform it to an rvalue you should use std::move at the call site:
some_func( a, std::move(obj) );
I doubt this could be optimized, since it's not clear whether you will use the temporary again or not:
Foo x = get_foo(); // using best-possible constructor and (N)RVO anyway
do_something(x);
do_something_else(x);
//...
If you're really keen on exploiting move semantics somewhere (but be sure to profile first to see that this really matters), you can make this explicit with move:
Foo y = get_foo();
do_oneoff_thing(std::move(y)); // now y is no longer valid!
I'd say that if something is eligible for moving, then you might as well do the inlining yourself and do without the extra local variable. After all, what good is such a temporary variable if it is only used once? The only scenario that comes to mind is if the last use of the local variable can exploit move semantics, so you could add std::move to the final appearance. That sounds like a maintenance hazard though, and you'd really need a compelling reason to write that.
I don't think that the const & binding to a temporary to extend the lifetime is so common. As a matter of fact, in C++03, in many cases the copy can be elided by just passing by value and calling the function in what you call the inlined form: some_func( int_func(), obj_func() ), so the same problem that you are noticing in C++11 would occur in C++03 (in a slightly different way)
As of the const reference binding, in the event that obj_func() returns an object of type T, the above code is just a cumbersome way of doing T obj = obj_func(); that offers no advantage other than making people wonder why that was needed.
If obj_func() returns a type T1 derived from T, that trick enables you to ignore the exact return type, but that can also be achieved by using the auto keyword, so in either case, what you have is a local named variable obj.
The proper way to pass the obj into the function --if you are finished with it, and the function can move the value from obj to an internal object, would be to actually move:
some_func( a, std::move(obj) );