当前位置: 首页 > article >正文

右值引用和移动构造函数

右值引用

C++11 中的一个新特性,用于实现移动语义和完美转发。右值引用用 `&&` 表示,可以绑定到临时对象或将要被销毁的对象,是一种可修改的引用类型。

右值引用的主要作用有两个:

1. 实现移动语义:右值引用可以将资源所有权从一个对象转移到另一个对象,避免了不必要的内存分配和复制,提高了程序的性能和效率。

2. 实现完美转发:右值引用可以将参数按照原始类型精确地转发到下一层函数,避免了类型退化和多余的拷贝构造函数调用,提高了程序的灵活性和可维护性。

以下是一个简单的右值引用的例子,用于实现移动语义:

```cpp

#include <iostream>
#include <vector>

class MyVector {
public:
    MyVector() {
        std::cout << "Default constructor" << std::endl;
    }

    MyVector(const MyVector& other) {
        std::cout << "Copy constructor" << std::endl;
    }

    MyVector(MyVector&& other) {
        std::cout << "Move constructor" << std::endl;
    }

    ~MyVector() {
        std::cout << "Destructor" << std::endl;
    }
};

MyVector createVector() {
    MyVector v;
    return v; // 返回一个临时对象
}

int main() {
    std::vector<MyVector> vec;

    vec.push_back(MyVector()); // 调用默认构造函数和移动构造函数

    MyVector v = createVector(); // 调用默认构造函数和移动构造函数

    return 0;
}


```

在上面的代码中,我们定义了一个 `MyVector` 类,用于演示移动语义。在类中,我们定义了默认构造函数、拷贝构造函数和移动构造函数,并在每个构造函数中输出一条提示信息。在 `createVector` 函数中,我们创建了一个临时对象并返回。在 `main` 函数中,我们创建了一个 `std::vector` 容器,并向其中添加一个临时对象和一个从 `createVector` 函数中返回的对象。在程序运行时,我们可以看到输出的提示信息,其中有两次移动构造函数的调用,分别对应于临时对象和从 `createVector` 函数中返回的对象的转移。

通过使用右值引用,我们可以实现移动语义,避免了不必要的拷贝构造函数调用,提高了程序的性能和效率。

移动构造函数

移动构造函数是 C++11 中的一个新特性,用于实现移动语义。移动构造函数的作用是将一个对象的资源(如内存、文件句柄、网络连接等)所有权从一个对象转移到另一个对象,避免了不必要的内存分配和复制,提高了程序的性能和效率。

移动构造函数的特点有:

1. 接受一个右值引用作为参数,表示将要被移动的对象。

2. 将被移动对象的资源所有权转移到新对象中,使用移动语义。

3. 将被移动对象的指针置为 `nullptr`,避免重复释放。

以下是一个简单的移动构造函数的例子,用于演示移动语义:

```cpp

#include <iostream>

class MyString {
public:
    MyString() {
        std::cout << "Default constructor" << std::endl;
        data_ = nullptr;
        size_ = 0;
    }

    MyString(const char* str) {
        std::cout << "Constructor with const char*" << std::endl;
        size_ = std::strlen(str);
        data_ = new char[size_ + 1];
        std::strcpy(data_, str);
    }

    MyString(const MyString& other) {
        std::cout << "Copy constructor" << std::endl;
        size_ = other.size_;
        data_ = new char[size_ + 1];
        std::strcpy(data_, other.data_);
    }

    MyString(MyString&& other) {
        std::cout << "Move constructor" << std::endl;
        size_ = other.size_;
        data_ = other.data_;
        other.size_ = 0;
        other.data_ = nullptr;
    }

    ~MyString() {
        std::cout << "Destructor" << std::endl;
        delete[] data_;
    }

private:
    char* data_;
    size_t size_;
};

MyString createString() {
    MyString s("Hello, world!");
    return s; // 返回一个临时对象
}

int main() {
    MyString s1("Hello, world!"); // 调用构造函数
    MyString s2(s1); // 调用拷贝构造函数
    MyString s3(std::move(s1)); // 调用移动构造函数

    MyString s4 = createString(); // 调用移动构造函数

    return 0;
}


```

在上面的代码中,我们定义了一个 `MyString` 类,用于演示移动构造函数。在类中,我们定义了默认构造函数、构造函数(接受 `const char*` 类型的参数)、拷贝构造函数和移动构造函数,并在每个构造函数和析构函数中输出一条提示信息。在 `createString` 函数中,我们创建了一个临时对象并返回。在 `main` 函数中,我们创建了四个 `MyString` 对象,分别调用了默认构造函数、构造函数、拷贝构造函数和移动构造函数,以及从 `createString` 函数中返回的对象的移动构造函数。在程序运行时,我们可以看到输出的提示信息,其中有三次构造函数的调用和两次移动构造函数的调用,分别对应于对象的创建和转移。


http://www.kler.cn/a/18173.html

相关文章:

  • acwing算法基础02一高精度,前缀和,差分
  • CommandLineParser 使用
  • Springboot 启动端口占用如何解决
  • 灰狼优化算法
  • 【MySQL】数据库表连接简明解释
  • 【机器学习】平均绝对误差(MAE:Mean Absolute Error)
  • 网络机顶盒哪个牌子好?资深数码粉分享网络电视机顶盒排名
  • WRF模式
  • 如何建设智慧档案馆
  • 【Leetcode 161】【GO】相隔为 1 的编辑距离
  • @Async异步线程:Spring 自带的异步解决方案
  • 同步辐射散射数据处理:从测量到分析的全流程解析
  • Ubuntu18.04系统及相关软件安装恢复过程
  • MG100-Hi3798MV100-当贝纯净桌面卡刷固件包
  • 华为OD机试真题-24点运算【2023】【JAVA】
  • Linux安装canal
  • Go type关键字定义新类型和类型别名的区别
  • io,nio,aio区别
  • 测试开发如何进阶?需要哪些能力?吐血整理-你的进阶之路...
  • 深入理解移动端布局:Viewport与设备像素比
  • linux命令之kill详解
  • UICollectionView 实现整页翻动(每页3个cell)
  • Android 9.0 Camera2 拍照功能默认选前摄像头
  • 【论文阅读】A Comparative Study on Camera-Radar Calibration Methods
  • 如何提高执行力
  • 图数据库游记