It has been ten years since C++11, which introduced many new language features that further strengthened C++ while discouraging many.
T&& Doesn’t Always Mean “Rvalue Reference”
by Scott Meyers
Scott Meyers once said that T&& does not always represent an rvalue reference.
&& as function arguments
That’s right. The ampersand symbol is probably a point that discouraged many people when they first learned C++ or C++11. But it’s not that hard to figure out.
First of all, in non-template functions, && must represent an rvalue reference, so only rvalue type arguments can be accepted.
class A {
...
};
void foo(A&& a) {
...
}
Copy the code
The foo function can only take the following rvalue arguments.
foo(A{}); A a; foo(std::move(a)); A get_a() { A a; . return a; } foo(get_a());Copy the code
However, this call is incorrect and will fail to compile:
A a1;
A& ar = a1;
foo(ar); // ERROR
Copy the code
However, && in a template function does not represent an rvalue rreference. Such as:
template <typename T>
void bar(T&& t) {
...
}
Copy the code
This T&& is referred to as a forwarding reference in the C++ standard, commonly known as a universal reference and often translated as a universal reference. As the name implies, the parameters it can receive are not only rvalues, but also lvalues, so it is called universal. So T&& in the main problem is not an rvalue reference.
The template function bar(), which I mentioned above, can accept the following types of arguments (any type!) . Such as:
bar(A{});
A a;
bar(move(a));
bar(get_a());
A a1;
A& ar1 = a1;
bar(ar1);
const A& ar2 = a1;
bar(ar2);
Copy the code
However, the && in template functions are not all forward references. Such as:
template<typename T>
void bar(vector<T>&& tv) {
...
}
Copy the code
The parameter TV can only accept arguments of rvalue type.
Such as:
template<typename T>
void bar(const T&& v) {
...
}
Copy the code
With the const constraint, && is also an rvalue reference and can only be passed as an rvalue…
I’m sure you see the difference.
The && that receives the return value
Another area of confusion for && is not just when it comes to parameters, as described above. There is also ambiguity when receiving the return value from a function, which is often confusing.
class A { ... }; A&& a = test1(); Auto && a = test2(); // This && is also a forward referenceCopy the code
When used with auto and &&, it is also a forward reference (universal reference), so it can accept various types of function arguments.
However, if the type is explicitly specified (such as A) and then used with &&, then only rvalue references are represented and only rvalue arguments are accepted!
How’d it go? Did you get rid of it?