右值引用主要用于移动语义(Move semantics)和完美转发(Perfect forwarding)
Move semantics
Move semantics能转移一个对象到另一个对象上,避免不必要的内存拷贝,被拷贝对象不能在其它地方被引用。要实现Move semantics只要给类定义移动构造函数和可选的移动赋值操作:
class Memory {
public:
Memory(Memory&& other) noexcept {
_data = other._data;
_length = other._length;
other._data = nullptr;
other._length = 0;
}
Memory& operator=(Memory&& other) noexcept {
if (this != &other) {
delete[] _data;
_data = other._data;
_length = other._length;
other._data = nullptr;
other._length = 0;
}
return *this;
}
private:
void *_data{nullptr};
int _length{0};
}
Perfect forwarding
Perfect forwarding主要为了减少重载函数,主要是泛型函数用引用类型作为参数。
struct W
{
W(int&, int&) {}
};
struct Z
{
Z(const int&, const int&) {}
};
template <typename T, typename A1, typename A2>
T* factory(A1& a1, A2& a2) {
return new T(a1, a2);
}
int a = 4, b = 5;
W* pw = factory<W>(a, b); // OK
Z* pz = factory<Z>(2, 2); // Valid cause 2 is right value
把上面的泛型函数参数改成右值引用就能解决这个问题:
template <typename T, typename A1, typename A2>
T* factory(A1&& a1, A2&& a2)
{
return new T(std::forward<A1>(a1), std::forward<A2>(a2));
}
Z* pz = factory<Z>(2, 2); // OK
References: https://learn.microsoft.com/en-us/cpp/cpp/rvalue-reference-declarator-amp-amp?view=msvc-170