左值,右值,引用,指针,常量,auto如何组合?
-
左值引用:
int &a = b;
- 左值引用是通过使用
&
符号来声明的,例如int &a
。 - 左值引用用于绑定到左值(可标识的、持久的、具名的),a绑定到b。
- 左值引用允许对其绑定的对象进行修改。
- 使用左值引用可以实现函数参数的传递和返回值的传递,以及在函数中进行对象的修改。
- 注意:如果b是一个临时对象,a就不能绑定到b,可以使用常量左值引用:编译器会创建一个临时的常量对象,并将右值的值复制到该临时对象中。
- 左值引用是通过使用
-
右值引用:
int &&a = b;
-
右值引用是通过使用
&&
符号来声明的,例如int &&a
。 -
右值引用用于绑定到右值b(临时的、匿名的、即将销毁的)。
-
右值引用通常用于实现移动语义和完美转发。
-
移动语义允许在对象之间高效地转移资源,而不是进行昂贵的拷贝操作。
-
完美转发允许保持传递给函数的参数的值类别(左值或右值),以便将其转发到其他函数。
-
-
-
常量左值引用:
- 常量左值引用是通过使用
const
修饰符和&
符号声明的,例如const int &a
。 - 常量左值引用用于绑定到左值,并且不允许修改绑定的对象。(也可以绑定到右值,但是不是真正的绑定到右值,而是创建一个临时常量对象复制右值的值到该对象中)
- 常量左值引用常用于函数参数中,以接受常量或临时对象,并避免对象的拷贝。
- 常量左值引用是通过使用
-
常量右值引用(×):
- 常量右值引用是一个错误的术语,因为常量对象的值是不可修改的,没有必要将其绑定到右值引用上。
- 右值引用本身可以是常量,例如
const int &&a
,但在实际使用中不常见。
-
指针常量:(const离*近说明指针是常量,const离名字ptr近,说明ptr是常量)
- 指针常量是指:指针本身是一个常量,即指针的值不可修改。
- 声明指针常量时在
*
之前添加const
关键字,例如const int* ptr
。 - 指针常量可以指向可变对象,但不能通过指针修改对象的值。但可以通过其他的指针或者引用来修改此值。
-
常量指针:
- 常量指针是指指针指向的对象是一个常量,即指针所指向的值不可修改。
- 声明常量指针时在
*
之后添加const
关键字,例如int* const ptr
。 - 常量指针本身的值可以修改,即可以指向不同的对象,但不能通过指针修改对象的值。
-
auto && a
为什么是万能转发:-
auto &&
是一种引用折叠(reference collapsing)的语法,用于实现完美转发。引用折叠:
A& &
变成A&
A& &&
变成A&
A&& &
变成A&
A&& &&
变成A&&
-
当
auto &&
用于模板函数参数类型时,它可以保持传递给函数的参数的值类别(左值或右值)。
-
-
std::move
什么时候使用-
移动语义作用是将一个对象的资源转移到另外一个对象, 这过程中避免了拷贝,节省了内存资源;通过std::move与右值引用即可实现移动语义;
-
std::move
是一个函数模板,用于将一个左值转换为对应的右值引用。当将一个对象标记为右值引用时,实际上只是改变了对象的类型,使其成为右值引用类型。对象本身的内存地址并没有改变。(并不是说因为右值没有内存地址,右值引用就会改变对象的内存地址) -
使用
std::move
可以显式地表示对象的所有权转移或资源移动的意图。 -
通常在使用移动语义的情况下使用
std::move
,例如在移动构造函数和移动赋值运算符中。
-
-
左值与右值:根本区别:左值可以取地址,而右值是没有存放在实际的地址空间里面的,一般是运算过程的中间值,他可能是寄存器里面的立即数等。总之他不放在地址空间中,因此不能对其取地址,自然也不能对他进行赋值了。