左值
对左值取别名
左值举例
int main()
{
//左值:可以取地址
int a = 10;
const int b = 20;
int* p = &a; //a,b,p均是左值
*p = 100; //*p也是左值
return 0;
}
左值引用举例
int main()
{
//以下 p、b、c、*p都是左值
int* P = new int(0);
int b = 1;
const int c = 2;
//以下是对左值的引用(取别名)
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;
return 0;
}
右值
int main()
{
//以下 p、b、c、*p都是左值
int* P = new int(0);
int b = 1;
const int c = 2;
//以下是对左值的引用(取别名)
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;
int x = 1.1, y = 2.2;
//以下为常见右值:不能取地址
10;
x + y;
fmin(x, y);
//右值引用
int&& rr1 = 10;
int&& rr2 = x + y;
int&& rr3 = fmin(x, y);
//左值引用右值
//double& r1 = x + y;
const double& r1 = x + y;
//右值引用左值,可以引用move后的左值
//int&& rr5 = b;
int&& rr5 = move(b);
return 0;
}
const T& x 既能接受左值又能接受右值
template<class T>
void Func(const T& x)
{
//x既能接收左值,又能接收右值
}
左值引用只能引用左值,不能引用右值,但是const左值引用既可以引用左值,又可以引用右值
右值引用只能引用右值,不能引用左值,但是可以引用move以后的左值
此处rr1和rr2是左值
引用的价值:减少拷贝
右值引用(Rvalue reference)是C++11引入的一种特性,它可以解决以下几个问题:
-
资源转移:右值引用允许对象的资源(如指针、文件句柄等)被转移到另一个对象,而不是进行深拷贝。这可以提高性能,特别是对于大型对象或容器类对象。通过移动语义,可以避免不必要的资源拷贝,减少内存和时间的开销。
-
完美转发:右值引用还允许完美转发(Perfect Forwarding),即将参数以原样传递给另一个函数,而不会丢失其值类别(左值或右值)。这对于泛型编程非常有用,可以保留传递参数的准确类型信息,并将其传递给下一个函数。
-
临时对象的优化:右值引用可以优化临时对象的创建和销毁。临时对象是指在表达式中创建的临时对象,例如函数返回值、临时变量等。通过使用右值引用,可以避免不必要的拷贝构造和析构函数的调用,提高性能。
-
移动语义:右值引用是实现移动语义的基础。移动语义允许对象的资源被转移,而不是进行深拷贝。这对于容器类对象、动态分配的内存等资源管理非常有用,可以提高性能和效率。
移动赋值||移动拷贝||移动构造
移动赋值(Move Assignment)是C++11引入的一种特性,它允许对象之间的资源转移,而不是进行深拷贝。移动赋值通常用于提高性能,特别是对于大型对象或容器类对象。
移动赋值操作符使用双引号(&&
)作为参数,并且通常返回一个引用。它的语法如下:
class MyClass {
public:
// 移动赋值操作符
MyClass& operator=(MyClass&& other) {
// 执行资源转移操作
// ...
return *this;
}
};
移动赋值操作符接受一个右值引用参数(MyClass&& other
),表示要转移资源的对象。在函数体内部,你可以执行资源的转移操作,例如将指针或资源所有权从other
对象转移到当前对象。最后,返回一个引用以支持链式赋值操作。
移动拷贝(Move Copy)是指在C++11中引入的一种特性,它允许通过移动语义来进行对象的拷贝操作。移动拷贝通常用于避免不必要的对象拷贝,提高性能。
移动拷贝操作符使用双引号(&&
)作为参数,并且通常返回一个新的对象。它的语法如下:
class MyClass {
public:
// 移动拷贝操作符
MyClass(MyClass&& other) {
// 执行资源转移操作
// ...
}
};
移动拷贝操作符接受一个右值引用参数(MyClass&& other
),表示要拷贝的对象。在函数体内部,你可以执行资源的转移操作,例如将指针或资源所有权从other
对象转移到新创建的对象。
移动构造(Move Construction)是指使用移动语义来创建新对象的过程。移动构造通常用于避免不必要的对象拷贝,提高性能。
移动构造函数使用双引号(&&
)作为参数,并且不需要返回任何值。它的语法如下:
class MyClass {
public:
// 移动构造函数
MyClass(MyClass&& other) {
// 执行资源转移操作
// ...
}
};
移动构造函数接受一个右值引用参数(MyClass&& other
),表示要创建新对象的源对象。在函数体内部,你可以执行资源的转移操作,例如将指针或资源所有权从other
对象转移到新创建的对象。
需要注意的是,移动赋值、移动拷贝和移动构造都是使用右值引用参数(&&
)来实现的,这是C++11引入的一种特性,用于表示临时对象或可以被转移资源的对象。
希望这可以帮助你理解移动赋值、移动拷贝和移动构造的概念!如果还有其他问题,请随时提问。
万能引用
t既可以引用左值也可以引用右值
void Fun(int& x) { cout << "左值引用" << endl; }
void Fun(const int& x) { cout << "const 左值引用" << endl; }
void Fun(int&& x) { cout << "右值引用" << endl; }
void Fun(const int&& x) { cout << "const 右值引用" << endl; }
template<typename T>
void PerfectForward(T&& t)
{
Fun(t);
//完美转发 保持原属性
Fun(std::forward<T>(t));
}
传左值就是左值&&会被折叠为&
传右值会变成左值(t为左值)
若一直为万能引用属性会丢失