左值引用与右值引用

左值引用和右值引用的区别?右值引用的意义

  • 左值引用是对左值的引用,右值引用是对右值的引用

    • 左值右值的概念

      • 左值:可以在等号左边,能够取地址,并且具备名字的(左值可以放在右边,只要能够放在等号左边就是左值)(const左值引用能指引右值,局限是不能修改这个值)

        • int i = 0;//运行流程是i+1之后被赋值10 ++i = 10; //表达式的结果是左值引用,指向 i 的内存地址
        • (i=9) = 100;//(i=9)可以做为做值,能够取到地址,且具备名字 (i+=10) = 1000;//(i+=10)可以作为左值
        • 解引用(操作符是* 例如:*ptr。解引用是指将指针转换为实际值或对象的过程。)也可以作为左值

          int* ptr = new int(10); *ptr = 20; // 解引用作为左值
      • 右值只能在等号右边,不能够取地址,不具备名字的(关键是如何区分右值)(右值指的是不具备“可修改状态”的表达式)

        • 纯右值:字面值

          int getValue() {return 10;} int main() {int a = getValue(); // 右值赋值到左值 return 0;} --------------------------------------------------- void myFunction(int&& value) {// do something} int main() {myFunction(getValue()); // 右值作为函数参数 return 0;} //在上述代码中,myFunction()函数的参数类型为int&&,表示该参数为右值引用类型,可以接受值作为参数。
          • int i = 10,这个10是纯右值

          • 返回非引用类型的函数调用

          • 后置自增/自减

            • int x = 10; int y = x++; // x 先赋值给 y,再进行自增 //这里的 x++ 表示先将 x 的值赋给 y,然后再将 x 自增,由于自增操作返回的是自增前的值,因此 x++ 是一个右值 //举个反例子int y = ++x; //其中++x是一个左值引用
        • 将亡值:c++11引入的一个与右值引用(移动语义:移动语义是指通过移动资源的所有权而不是复制资源,来提高代码性能的C++语言特性)相关的值类型

        • std::vector<int> createVector() { std::vector<int> v = {1, 2, 3}; return v;} int main() { std::vector<int> v2 = createVector(); // 这里会调用移动构造函数 return 0;} //在createVector()函数中,我们创建了一个std::vector<int>类型的局部变量v,并在函数结束时将其返回。由于返回值是一个临时变量,这个临时变量在调用函数结束时就会被销毁。因此,在将其返回时,编译器会自动使用移动构造函数将其转换为一个将亡值,以便在函数调用结束时将其移动到调用方的变量v2中。
          • 用将亡值来触发移动构造注1/移动赋值构造并进行资源转移,之后将调用析构函数注2
      • 左值右值的区别

  • 左值引用

    • 避免对象的拷贝,可以直接使用内容
    • const左值引用能指引右值,局限是不能修改这个值
    • 声明出来的左值引用或者右值引用都是左值
  • 右值引用

    • 意义:
      • 实现移动语义
      • 实现完美转发
    • 通过std::move()实现指向左值

声明出来的左值引用或者右值引用都是左值,左值引用是对左值的引用,右值的引用是对右值的引用,两者都是引用,声明出来的变量都是左值,比如说int &a和int &&a中的a都是左值。const左值引用可以指向右值,const int &a就可以引用右值,但是不能修改这个值,因此需要右值引用解决这个问题右值引用也可以指向左值,可以通过move函数指向这个左值。


注1移动构造函数

​ 移动构造是一种特殊的构造函数,用于将一个对象的资源(比如内存)转移到另一个对象,同时避免不必要的内存拷贝,从而提高程序性能。通常情况下,移动构造函数会接受一个将亡值(即将被销毁的对象),并将其资源转移到一个新的对象中,然后将将亡值的指针置为null,避免其析构函数再次释放资源。

class MyString { public: // 构造函数 MyString(const char* str) { std::size_t size = std::strlen(str) + 1; data_ = new char[size]; std::strcpy(data_, str); } // 移动构造函数 MyString(MyString&& other) { data_ = other.data_; other.data_ = nullptr; } // 析构函数 ~MyString() { delete[] data_; } private: char* data_; }; //在使用该类的过程中,可能会发生对象的拷贝,如下所示: MyString s1("Hello"); MyString s2(s1); // 拷贝构造 //这时候,由于 s1 和 s2 都有自己的数据存储,因此需要进行数据的复制,这样就浪费了一部分时间和内存空间。而如果使用移动构造函数,则可以直接将 s1 的数据指针 data_ 赋给 s2,避免了数据的复制: MyString s1("Hello"); MyString s2(std::move(s1)); // 移动构造 //在移动构造的过程中,由于 s1 的数据指针 data_ 已经被转移给了 s2,因此 s1 的析构函数就不再需要删除 data_ 了,避免了重复删除已经被释放的内存空间。

构造函数:

​ 构造函数是一种特殊的成员函数,用于创建和初始化对象。当定义一个对象时,构造函数会自动调用来初始化对象的数据成员。

class MyClass { public: int x; // 构造函数 MyClass(int val) { x = val; std::cout << "MyClass object is created with x = " << x << std::endl; } }; int main() { MyClass obj(10); // 使用构造函数创建对象 return 0; } //在上面的示例中,MyClass 类有一个带有一个整数参数的构造函数,用于初始化类中的数据成员 x。在 main 函数中,我们创建了一个名为 obj 的 MyClass 类型的对象,并将值 10 传递给构造函数。,这表明构造函数被成功调用,并使用传递的值 10 初始化了 x 数据成员。

构造函数的作用可以总结为以下几点:

  1. 初始化对象的成员变量,确保对象在创建后的初始状态是正确的。
  2. 分配内存或资源,并对其进行初始化,如动态分配内存、打开文件、连接网络等。
  3. 对象创建时执行一些必要的操作,如日志记录、统计等。
  4. 可以提供默认参数,方便用户使用。

注2

​ 析构函数的作用是在对象被销毁时自动执行清理操作,如释放对象所占用的内存等。当一个对象的生命周期结束时,C++编译器会自动调用其析构函数。

class MyClass { public: MyClass() { std::cout << "MyClass constructor called" << std::endl; } ~MyClass() { std::cout << "MyClass destructor called" << std::endl; } }; int main() { MyClass myObj; return 0; } //在上述代码中,我们定义了一个名为MyClass的类,其中包含了一个构造函数和一个析构函数。在main函数中,我们创建了一个MyClass对象myObj,并在程序结束时销毁它。由于MyClass包含了一个析构函数,因此在myObj被销毁时,其析构函数会自动被调用,输出一条提示信息。

__EOF__

本文作者Lachlan_Yang
本文链接https://www.cnblogs.com/LaChlanYang/p/17217775.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Lachlan_Yang  阅读(865)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示