跳到主要内容

右值引用

本文是基于右值引用的应用

移动语义

Move Semantics

定义

传统 C++ 通过拷贝构造函数和赋值操作符为类对象设计了拷贝/复制的概念
但为了实现对资源的移动操作,调用者必须使用先复制、再析构的方式
否则就需要自己实现移动对象的接口
试想,搬家的时候应该是把家里的东西直接搬到新家去
而不是将所有东西复制一份(重买)再放到新家、再把原来的东西全部扔掉(销毁)

右值引用解决了拷贝复制带来的资源浪费问题

移动语义是在右值引用的基础上引入的
将一个对象的内容移动到另一个对象的操作

在拷贝语义中,会调用类的拷贝构造函数或者赋值构造函数
在移动语义中,会调用类的移动构造函数
这句话的意思是当赋值的变量或者类构造参数为左值时,会调用类的那个有左值参数的构造函数;
当其为右值时,会调用类的那个有右值引用参数的重载构造函数

class TA {
int* a;
TA() {
}
TA(const TA& lvalue) {
a = new int(*lvalue.a);
}//拷贝语义
TA(const TA&& rvalue) {
a = rvalue.a;
}//移动语义
};

std::move

作用是把左值强转为右值

完美转发

Perfect Forwarding

std::forward

保持参数的引用类型

template<typename T>
void print(T& t) {
std::cout << "L" << std::endl;
}

template<typename T>
void print(T&& t) {
std::cout << "R" << std::endl;
}

template<typename T>
void testForward(T&& v) {
print(v);//始终调用左值重载的print
print(std::forward<T>(v)); //保持实参的值类型
print(std::move(v)); //始终调用右值重载的print
}

int main(int argc, char* argv[])
{
int x = 1;
testForward(x); //实参为左值
testForward(std::move(x)); //实参为右值
}

// 结果为:
// L
// L
// R
// L
// R
// R