Rvalue reference and auto&& local variables - c++

What is the point of defining a local variable to be an rvalue reference or a forwarding (universal) reference? As far as I understand, any variable that has a name is an lvalue and will be treated as such moving forward.
Example:
Widget&& w1 = getWidget();
auto&& w2 = getWidget();
w1 and w2 are both lvalues, and will be treated as such if they're passed as arguments later on. Their decltype is probably not, but what difference does this make? Why would anyone need to define variables that way?

If you have a function returning a temporary which cannot be moved.
Foo some_function();
auto&& f = some_function();
This is legal. auto f = some_function(); will either copy (which could be expensive), or fail to compile (if the class also cannot be copied).
In general, auto&& deduces down to either an r or lvalue reference depending on what it is initialized with, and if initialized with a temporary extends its lifetime while giving you access to it as an lvalue.
A classic use is in the 'just-loop' pattern:
for( auto&& x : some_range )
where there is actually a auto&& x = *it; in the code generated.
You cannot bind a non-constant lvalue reference to a temporary, so your other choice is Widget const&, which doesn't let you modify the temporary during its lifetime.
This technique is also useful to decompose a complex expression and see what is going on. So long as you aren't working with extremely fragile expression templates, you can take the expression a+b+c*d and turn it into
auto&& c_times_d = d*d;
auto&& b_plus_c_times_d = b + decltype(c_times_d)c_times_d;
auto&& c_plus_b_plus_c_times_d = c + decltype(b_plus_c_times_d)b_plus_c_times_d;
and now you have access to the temporary objects whose lifetime is extended, and you can easily step through the code, or introduce extra steps between steps in a complex expression: and this happens mechanically.
The concern about fragile expression templates only holds if you fail to bind every sub-expression. (Note that using -> can generate a myriad of sub-expressions you might not notice.)
I use auto&& when I want to say "I'm storing the return value of some function, as is, without making a copy", and the type of the expression is not important. auto is when I want to make a local copy.
In generic code it can be highly useful.
Foo const& a(Foo*);
Bar a(Bar*);
template<class T>
auto do_stuff( T*ptr ) {
auto&& x = a(ptr);
}
here if you pass a Bar* it stores the temporary, but if you pass a Foo* to do_stuff it stores the const&.
It does the least it can.
Here is an example of a function returning a non-movable non-copyable object, and how auto&& lets you store it. It is otherwise useless, but it shows how it works:
struct Foo {
Foo(&&)=delete;
Foo(int x) { std::cout << "Foo " << x << " constructed\n";
};
Foo test() {
return {3};
}
int main() {
auto&& f = test();
}

As far as I know, there is no real, aka widely used purpose to define a local rvalue reference, since their nature, to not to bind to lvalues, is only helpful in overloading and deduction, so to define them as parameters of a function.
One could use them, to bind them to temporary values like
int &&rref = 5*2;
but since almost all compilers are optimizing the expression
int i = 5*2;
there is no real need, in therm of performance or avoid copying.

One example could be an array
template<class T, int N> using raw_array = T[N];
then
auto && nums = raw_array<int,4>{101, 102, 103, 104};
this allows the temporary to be used as if it was an ordinary array.

A variable declared auto&& will follow perfect forwarding rules. Try it for yourself. This is even how perfect forwarding is done with lambdas in c++14.
const Type& fun1();
Type&& fun2();
auto&& t1 = fun1(); // works
auto&& t2 = fun2(); // works too

Related

f = std::forward in lambda capture, what does it mean?

I have the following code which is used to call a function on an object and pass any argument in a perfect-forwarding way
template <typename F, typename T>
inline auto call_with_args(F&& f, T&& t) {
return [f = std::forward<F>(f), t = std::forward<T>(t)]
(auto&&... args) mutable { return (t.*f)(std::forward<decltype(args)>(args)...); };
}
I'm trying to read this but I'm unsure what [f = std::forward<F>(f)] does. That is the 'capture by value' syntax, but what does that have to do with std::forward (which is a cast to rvalue reference from what I could read)? Is it re-defining f with a new variable which gets assigned whatever type and value category f had after being universal-reference-bound to the function parameter f?
Can somebody explain this to me in simple terms please?
f and t are what as known as forwarding references and like all references, they are considered an lvalue, even if they refer to an rvalue.
So, since they are lvalues if you just captured them by value like
return [f, t](...) { ... };
Then f and t will be copied into the closure object as they are lvalues. This isn't great as we are missing out on being able to move f and t if they refer to rvalues . To avoid this we use std::forward which cast rvalues back to rvalues while leaving lvalues as lvalues.
That gives you the syntax of
return [f = std::forward<F>(f)](...) { ... };
which says create a member of the lambda named f and initialize it with std::forward<F>(f) where that f is the f from the surrounding scope.
Let's go through it one by one:
If an lvalue reference is passed in, f = ... will have an lvalue reference as the .... A copy is made.
If an rvalue reference is passed in, f = ... will have an rvalue as the .... This means that the value is moved into the lambda capture instead.
As a result, the code saves on making a copy when it's passed an rvalue reference.
There's another way that achieves the same thing and is potentially a little less confusing to the reader: If you're going to keep the object anyway, just take it by value, then move.
template <typename F, typename T>
inline auto call_with_args(F f, T t) {
return [f = std::move(f), t = std::move(t)]
(auto&&... args) mutable { return (t.*f)(std::forward<decltype(args)>(args)...); };
}
That's a bit easier to reason about and achieves the same thing: A copy when an lvalue is passed in, and no copy when an rvalue (temporary) is passed in. (It does use one extra move, so if your objects are potentially expensive to move like std::array, you might want to stick to the original version.)

What are the use cases of class member functions marked &&?

I don't know which C++ standard presented this feature, but I cannot think of any use cases of this.
A member functions with && modifier will only be considered by overload resolution if the object is rvalue
struct Foo
{
auto func() && {...}
};
auto a = Foo{};
a.func(); // Does not compile, 'a' is not an rvalue
std::move(a).func(); // Compiles
Foo{}.func(); // Compiles
Can someone please explain the use case for this?
Why we ever want some routine to be performed only for rvalues?
Ref-qualification was added in c++11. In general, propagation of the value-category is incredibly useful for generic programming!
Semantically, ref-qualifications on functions help to convey the intent; acting on lvalue references or rvalues -- which is analogous to const or volatile qualifications of functions. These also parallel the behavior of struct members, which propagate the qualifiers and categories.
A great example of this in practice is std::optional, which provides the std::optional::value() function, which propagates the value-category to the reference on extraction:
auto x = std::move(opt).value(); // retrieves a T&&
This is analogous to member-access with structs, where the value-category is propagated on access:
struct Data {
std::string value;
};
auto data = Data{};
auto string = std::move(data).value; // expression yields a std::string&&
In terms of generic composition, this massively simplifies cases where the input may be an lvalue or an rvalue. For example, consider the case of using forwarding references:
// Gets the internal value from 'optional'
template <typename Optional>
auto call(Optional&& opt) {
// will be lvalue or rvalue depending on what 'opt' resolves as
return std::forward<Optional>(opt).value();
}
Without ref-qualification, the only way to accomplish the above code would be to create two static branches -- either with if constexpr or tag-dispatch, or some other means. Something like:
template <typename Optional>
auto call(Optional&& opt) {
if constexpr (std::is_lvalue_reference_v<Optional>) {
return opt.value();
} else {
return std::move(opt.value());
}
}
On a technical level, rvalue-qualifications on functions provides the opportunity to optimize code with move-constructions and avoid copies in a semantically clear way.
Much like when you see a std::move(x) on a value, you are to expect that x is expiring; it's not unreasonable to expect that std::move(x).get_something() will cause x to do the same.
If you combine && overloads with const & overloads, then you can represent both immutable copying, and mutating movements in an API. Take, for example, the humble "Builder" pattern. Often, Builder pattern objects hold onto pieces of data that will be fed into the object on construction. This necessitates copies, whether shallow or deep, during construction. For large objects, this can be quite costly:
class Builder {
private:
// Will be copied during construction
expensive_data m_expensive_state;
...
public:
auto add_expensive_data(...) -> Builder&;
auto add_other_data(...) -> Builder&;
...
auto build() && -> ExpensiveObject {
// Move the expensive-state, which is cheaper.
return ExpensiveObject{std::move(m_expensive_state), ...}
}
auto build() const & -> ExpensiveObject
// Copies the expensive-state, whcih is costly
return ExpensiveObject{m_expensive_state, ...}
}
...
};
Without rvalue-qualifications, you are forced to make a choice on the implementation:
Do destructive actions like moves in a non-const function, and just document the safety (and hope the API isn't called wrong), or
Just copy everything, to be safe
With rvalue-qualifications, it becomes an optional feature of the caller, and it is clear from the authored code what the intent is -- without requiring documentation:
// Uses the data from 'builder'. May be costly and involves copies
auto inefficient = builder.build();
// Consumes the data from 'builder', but makes 'efficient's construction
// more efficient.
auto efficient = std::move(builder).build();
As an added benefit, static-analysis can often detect use-after-move cases, and so an accidental use of builder after the std::move can be better caught than simple documentation could.
What are the use cases of class member functions marked &&?
A use case are "getter" style functions. They traditionally return references to sub objects or owned objects whose lifetime is tied to the super object.
That is however sometimes problematic, since calling the getter on an rvalue will result in a reference to an object that will be destroyed at the end of the expression. That is unsafe:
struct demo {
int& get_mem() { return mem; }
private:
int mem;
};
demo get_demo();
int& ref = get_demo().get_mem();
std::cout << ref; // bug
An lvalue ref qualifier prevents such bugs:
int& get_mem() & { return mem; }
int& ref = get_demo().get_mem(); // safely ill-formed
But it also prevents working previously correct code such as:
std::cout << get_demo().get_mem(); // used to be OK; now ill-formed
A solution is to provide two overloads, each with different qualifier:
int& get_mem() & { return mem; }
int get_mem() && { return mem; }
It is commonly used with types that wrap other types, with a full set of overloads that simulate all constess and value categories:
const int& get_mem() const& ;
int& get_mem() & ;
const int&& get_mem() const&&;
int&& get_mem() &&;

Is there any reason to capture a return-value as an rvalue-reference?

I have a move-only struct Foo, and a function Foo get();
If I want to capture the return value of get in a mutable manner, I have two options:
by value (Foo)
by rvalue-reference (Foo&&)
When I capture by rvalue-reference I create an lvalue, much like capturing by value.
I'm struggling to see the point between the different options?
Is there any difference between these two?
Working example:
#include <iostream>
struct Foo
{
Foo(std::string s) : s(std::move(s)) {}
Foo(Foo&& f) : s(std::move(f.s)) {}
Foo(const Foo&) = delete;
Foo& operator=(const Foo&) = delete;
std::string s;
};
Foo get()
{
return Foo { "hello" };
}
int main()
{
// capture return value as l-value
Foo lv1 = get();
// move into another lvalue
Foo lv2 = std::move(lv1);
std::cout << lv2.s << '\n';
// capture return value as r-value reference
Foo&& rv1 = get();
// move into another lvalue
Foo lv3 = std::move(rv1);
std::cout << lv3.s << '\n';
return 0;
}
Foo lv1 = get();
This requires that Foo is copy/moveable.
Foo&& rv1 = get();
This does not (at least, not as far as this line of code is concerned; the implementation of get may still require one).
Even though compilers are permitted to elide the copy of the return value into the variable, copy initialization of this form still requires the existence of an accessible copy or move constructor.
So if you want to impose as few limitations on the type Foo as possible, you can store a && of the returned value.
Of course, C++17 changes this rule so that the first one doesn't need a copy/move constructor.
Foo&&
this creates a reference to a temporary value (or stores a rvalue reference assigned to it). If it stores a reference to a temporary value, its lifetime extends the value.
Foo
This stores a copy of the value, regardless of what was returned.
In C++11 and 14, if Foo cannot be moved, assigning Foo make_foo() to a variable of type Foo is illegal. There is a move there, even if the move is elided (and the return value and the value in the outer scope have merged lifetimes).
In C++17, guaranteed elision means that no move constructor need exist.
Foo x = make_foo(); // Foo make_foo()
the above in C++17 guarantees that the return value of make_foo() is just named x. In fact, a temporary within make_foo may also be x; the same object, with different names. No move need occur.
There are a few other subtle differences. decltype(x) will return the declared type of x; so Foo or Foo&& depending.
Another important difference is its use with auto.
auto&& x = some_function();
this creates a reference to anything. If some_function returns a temporary, it binds an rvalue reference to it and extends its lifetime. If it returns a reference, x matches the type of the reference.
auto x = some_function();
this creates a value, which may be copied from what some_function returns, or may be elided with the return value of some_function if it returns a temporary.
auto&& means, in a sense, "just make it work, and don't do extra work", and it could deduce to a Foo&&. auto means "store a copy".
In the "almost always auto" style, these will be more common than an explicit Foo or Foo&&.
auto&& will never deduce to Foo, but can deduce to Foo&&.
The most common uses of auto&&, even outside of almost always auto, would be:
for(auto&& x : range)
where x becomes an efficient way to iterate over the range, where we don't care what type range has much. Another common use is:
[](auto&& x){ /* some code */ }
lambdas are often used in contexts where the type is obvious and not worth typing again, like being passed to algorithms or the like. By using auto&& for parameter types we make the code less verbose.

How to write a generic forwarding lambda in C++14?

How do I write a generic forwarding lambda in C++14?
Try #1
[](auto&& x) { return x; }
Inside the function body, x is an lvalue, so this doesn't work.
Try #2
[](auto&& x) { return std::forward<decltype(x)>(x); }
This properly forwards references inside the lambda, but it will always return by value (unless the compiler elides the copy).
Try #3
[](auto&& x) -> decltype(x) { return std::forward<decltype(x)>(x); }
This returns the same type as the argument (probably -> auto&& would work as well) and appears to work properly.
Try #4
[](auto&& x) noexcept -> decltype(x) { return std::forward<decltype(x)>(x); }
Does adding noexcept make this lambda more applicable and thus strictly better than #3?
A return type of decltype(x) is insufficient.
Local variables and function parameters taken by value can be implicitly moved into the return value, but not function parameters taken by rvalue reference (x is an lvalue, even though decltype(x) == rvalue reference if you pass an rvalue). The reasoning the committee gave is that they wanted to be certain that when the compiler implicitly moves, no one else could possibly have it. That is why we can move from a prvalue (a temporary, a non-reference qualified return value) and from function-local values. However, someone could do something silly like
std::string str = "Hello, world!";
f(std::move(str));
std::cout << str << '\n';
And the committee didn't want to silently invoke an unsafe move, figuring that they should start out more conservative with this new "move" feature. Note that in C++20, this issue will be resolved, and you can simply do return x and it will do the right thing. See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0527r0.html
For a forwarding function, I would attempt to get the noexcept correct. It is easy here since we are just dealing with references (it is unconditionally noexcept). Otherwise, you break code that cares about noexcept.
This makes the final ideal forwarding lambda look as follows:
auto lambda = [](auto && x) noexcept -> auto && { return std::forward<decltype(x)>(x); };
A return type of decltype(auto) will do the same thing here, but auto && better documents that this function always returns a reference. It also avoids mentioning the variable name again, which I suppose makes it slightly easier to rename the variable.
As of C++17, the forwarding lambda is also implicitly constexpr where possible.
Your first two tries don't work because return type deduction drops top-level cv-qualifiers and references, which makes generic forwarding impossible. Your third is exactly correct just unnecessarily verbose, the cast is implicit in the return type. And noexcept is unrelated to forwarding.
Here are a few more options worth throwing out for completeness:
auto v0 = [](auto&& x) -> decltype(x) { return x; };
auto v1 = [](auto&& x) -> auto&& { return x; };
auto v2 = [](auto&& x) -> auto&& { return std::forward<decltype(x)>(x); };
auto v3 = [](auto&& x) -> decltype(auto) { return std::forward<decltype(x)>(x); };
v0 will compile and look as if it returns the correct type, but will fail at compilation if you call it with an rvalue reference due to the requested implicit conversion from lvalue reference (x) to rvalue reference (decltype(x)). This fails on both gcc and clang.
v1 will always return an lvalue reference. If you call it with temporary, that gives you a dangling reference.
Both v2 and v3 are correct, generic forwarding lambdas. Thus, you have three options for your trailing return type (decltype(auto), auto&&, or decltype(x)) and one option for the body of your lambda (a call to std::forward).
The fewest characters, yet fully featured, version I can generate is:
[](auto&&x)noexcept->auto&&{return decltype(x)(x);}
this uses an idiom I find useful -- when forwarding auto&& parameters in a lambda, do decltype(arg)(arg). Forwarding the decltype through forward is relatively pointless if you know that the arg is of reference type.
If x was of value type, decltype(x)(x) actually produces a copy of x, while std::forward<decltype(x)>(x) produces an rvalue reference to x. So the decltype(x)(x) pattern is less useful in the general case than forward: but this isn't the general case.
auto&& will allow references to be returned (matching the incoming references). Sadly, reference lifetime extension won't work properly with the above code -- I find that forwarding rvalue references into rvalue references is often the wrong solution.
template<class T>struct tag{using type=T;};
template<class Tag>using type=typename Tag::type;
template<class T> struct R_t:tag<T>{};
template<class T> struct R_t<T&>:tag<T&>{};
template<class T> struct R_t<T&&>:tag<T>{};
template<class T>using R=type<R_t<T>>;
[](auto&&x)noexcept->R<decltype(x)>{return decltype(x)(x);}
gives you that behavior. lvalue references become lvalue references, rvalue references become values.

What does auto&& tell us?

If you read code like
auto&& var = foo();
where foo is any function returning by value of type T. Then var is an lvalue of type rvalue reference to T. But what does this imply for var? Does it mean, we are allowed to steal the resources of var? Are there any reasonable situations when you should use auto&& to tell the reader of your code something like you do when you return a unique_ptr<> to tell that you have exclusive ownership? And what about for example T&& when T is of class type?
I just want to understand, if there are any other use cases of auto&& than those in template programming; like the ones discussed in the examples in this article Universal References by Scott Meyers.
By using auto&& var = <initializer> you are saying: I will accept any initializer regardless of whether it is an lvalue or rvalue expression and I will preserve its constness. This is typically used for forwarding (usually with T&&). The reason this works is because a "universal reference", auto&& or T&&, will bind to anything.
You might say, well why not just use a const auto& because that will also bind to anything? The problem with using a const reference is that it's const! You won't be able to later bind it to any non-const references or invoke any member functions that are not marked const.
As an example, imagine that you want to get a std::vector, take an iterator to its first element and modify the value pointed to by that iterator in some way:
auto&& vec = some_expression_that_may_be_rvalue_or_lvalue;
auto i = std::begin(vec);
(*i)++;
This code will compile just fine regardless of the initializer expression. The alternatives to auto&& fail in the following ways:
auto => will copy the vector, but we wanted a reference
auto& => will only bind to modifiable lvalues
const auto& => will bind to anything but make it const, giving us const_iterator
const auto&& => will bind only to rvalues
So for this, auto&& works perfectly! An example of using auto&& like this is in a range-based for loop. See my other question for more details.
If you then use std::forward on your auto&& reference to preserve the fact that it was originally either an lvalue or an rvalue, your code says: Now that I've got your object from either an lvalue or rvalue expression, I want to preserve whichever valueness it originally had so I can use it most efficiently - this might invalidate it. As in:
auto&& var = some_expression_that_may_be_rvalue_or_lvalue;
// var was initialized with either an lvalue or rvalue, but var itself
// is an lvalue because named rvalues are lvalues
use_it_elsewhere(std::forward<decltype(var)>(var));
This allows use_it_elsewhere to rip its guts out for the sake of performance (avoiding copies) when the original initializer was a modifiable rvalue.
What does this mean as to whether we can or when we can steal resources from var? Well since the auto&& will bind to anything, we cannot possibly try to rip out vars guts ourselves - it may very well be an lvalue or even const. We can however std::forward it to other functions that may totally ravage its insides. As soon as we do this, we should consider var to be in an invalid state.
Now let's apply this to the case of auto&& var = foo();, as given in your question, where foo returns a T by value. In this case we know for sure that the type of var will be deduced as T&&. Since we know for certain that it's an rvalue, we don't need std::forward's permission to steal its resources. In this specific case, knowing that foo returns by value, the reader should just read it as: I'm taking an rvalue reference to the temporary returned from foo, so I can happily move from it.
As an addendum, I think it's worth mentioning when an expression like some_expression_that_may_be_rvalue_or_lvalue might turn up, other than a "well your code might change" situation. So here's a contrived example:
std::vector<int> global_vec{1, 2, 3, 4};
template <typename T>
T get_vector()
{
return global_vec;
}
template <typename T>
void foo()
{
auto&& vec = get_vector<T>();
auto i = std::begin(vec);
(*i)++;
std::cout << vec[0] << std::endl;
}
Here, get_vector<T>() is that lovely expression that could be either an lvalue or rvalue depending on the generic type T. We essentially change the return type of get_vector through the template parameter of foo.
When we call foo<std::vector<int>>, get_vector will return global_vec by value, which gives an rvalue expression. Alternatively, when we call foo<std::vector<int>&>, get_vector will return global_vec by reference, resulting in an lvalue expression.
If we do:
foo<std::vector<int>>();
std::cout << global_vec[0] << std::endl;
foo<std::vector<int>&>();
std::cout << global_vec[0] << std::endl;
We get the following output, as expected:
2
1
2
2
If you were to change the auto&& in the code to any of auto, auto&, const auto&, or const auto&& then we won't get the result we want.
An alternative way to change program logic based on whether your auto&& reference is initialised with an lvalue or rvalue expression is to use type traits:
if (std::is_lvalue_reference<decltype(var)>::value) {
// var was initialised with an lvalue expression
} else if (std::is_rvalue_reference<decltype(var)>::value) {
// var was initialised with an rvalue expression
}
First, I recommend reading this answer of mine as a side-read for a step-by-step explanation on how template argument deduction for universal references works.
Does it mean, we are allowed to steal the resources of var?
Not necessarily. What if foo() all of a sudden returned a reference, or you changed the call but forgot to update the use of var? Or if you're in generic code and the return type of foo() might change depending on your parameters?
Think of auto&& to be exactly the same as the T&& in template<class T> void f(T&& v);, because it's (nearly†) exactly that. What do you do with universal references in functions, when you need to pass them along or use them in any way? You use std::forward<T>(v) to get the original value category back. If it was an lvalue before being passed to your function, it stays an lvalue after being passed through std::forward. If it was an rvalue, it will become an rvalue again (remember, a named rvalue reference is an lvalue).
So, how do you use var correctly in a generic fashion? Use std::forward<decltype(var)>(var). This will work exactly the same as the std::forward<T>(v) in the function template above. If var is a T&&, you'll get an rvalue back, and if it is T&, you'll get an lvalue back.
So, back on topic: What do auto&& v = f(); and std::forward<decltype(v)>(v) in a codebase tell us? They tell us that v will be acquired and passed on in the most efficient way. Remember, though, that after having forwarded such a variable, it's possible that it's moved-from, so it'd be incorrect use it further without resetting it.
Personally, I use auto&& in generic code when I need a modifyable variable. Perfect-forwarding an rvalue is modifying, since the move operation potentially steals its guts. If I just want to be lazy (i.e., not spell the type name even if I know it) and don't need to modify (e.g., when just printing elements of a range), I'll stick to auto const&.
† auto is in so far different that auto v = {1,2,3}; will make v an std::initializer_list, whilst f({1,2,3}) will be a deduction failure.
Consider some type T which has a move constructor, and assume
T t( foo() );
uses that move constructor.
Now, let's use an intermediate reference to capture the return from foo:
auto const &ref = foo();
this rules out use of the move constructor, so the return value will have to be copied instead of moved (even if we use std::move here, we can't actually move through a const ref)
T t(std::move(ref)); // invokes T::T(T const&)
However, if we use
auto &&rvref = foo();
// ...
T t(std::move(rvref)); // invokes T::T(T &&)
the move constructor is still available.
And to address your other questions:
... Are there any reasonable situations when you should use auto&& to tell the reader of your code something ...
The first thing, as Xeo says, is essentially I'm passing X as efficiently as possible, whatever type X is. So, seeing code which uses auto&& internally should communicate that it will use move semantics internally where appropriate.
... like you do when you return a unique_ptr<> to tell that you have exclusive ownership ...
When a function template takes an argument of type T&&, it's saying it may move the object you pass in. Returning unique_ptr explicitly gives ownership to the caller; accepting T&& may remove ownership from the caller (if a move ctor exists, etc.).
The auto && syntax uses two new features of C++11:
The auto part lets the compiler deduce the type based on the context (the return value in this case). This is without any reference qualifications (allowing you to specify whether you want T, T & or T && for a deduced type T).
The && is the new move semantics. A type supporting move semantics implements a constructor T(T && other) that optimally moves the content in the new type. This allows an object to swap the internal representation instead of performing a deep copy.
This allows you to have something like:
std::vector<std::string> foo();
So:
auto var = foo();
will perform a copy of the returned vector (expensive), but:
auto &&var = foo();
will swap the internal representation of the vector (the vector from foo and the empty vector from var), so will be faster.
This is used in the new for-loop syntax:
for (auto &item : foo())
std::cout << item << std::endl;
Where the for-loop is holding an auto && to the return value from foo and item is a reference to each value in foo.