左值,右值,引用,指针,常量,auto如何组合?

发布时间 2023-08-06 16:03:25作者: 石中火本火

左值,右值,引用,指针,常量,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,例如在移动构造函数和移动赋值运算符中。

  • ​ 左值与右值:根本区别:左值可以取地址,而右值是没有存放在实际的地址空间里面的,一般是运算过程的中间值,他可能是寄存器里面的立即数等。总之他不放在地址空间中,因此不能对其取地址,自然也不能对他进行赋值了。