移动语义的简单示例

发布时间 2023-06-09 08:50:43作者: jobgeo

下面是一个使用移动语义的简单示例:

#include <iostream>
#include <string>
 
class MyString {
public:
    MyString() : m_data(nullptr), m_size(0) {}
 
    MyString(const char* str) : MyString() {
        m_size = strlen(str);
        m_data = new char[m_size + 1];
        strcpy_s(m_data, m_size + 1, str);
    }
 
    // 拷贝构造函数
    MyString(const MyString& other) : MyString() {
        if (other.m_data != nullptr) {
            m_size = other.m_size;
            m_data = new char[m_size + 1];
            strcpy_s(m_data, m_size + 1, other.m_data);
        }
    }
 
    // 移动构造函数
    MyString(MyString&& other) noexcept : m_data(other.m_data), m_size(other.m_size) {
        other.m_data = nullptr;
        other.m_size = 0;
    }
 
    ~MyString() { delete[] m_data; }
 
    // 赋值运算符重载(拷贝赋值)
    MyString& operator=(const MyString& other) {
        if (this != &other) {
            delete[] m_data;
            m_size = other.m_size;
            m_data = new char[m_size + 1];
            strcpy_s(m_data, m_size + 1, other.m_data);
        }
        return *this;
    }
 
    // 赋值运算符重载(移动赋值)
    MyString& operator=(MyString&& other) noexcept {
        if (this != &other) {
            delete[] m_data;
            m_data = other.m_data;
            m_size = other.m_size;
            other.m_data = nullptr;
            other.m_size = 0;
        }
        return *this;
    }
 
    char* getData() const { return m_data; }
    size_t getSize() const { return m_size; }
 
private:
    char* m_data;
    size_t m_size;
};
 
int main() {
    MyString s1("Hello");
    MyString s2(std::move(s1)); // 调用移动构造函数
    std::cout << "s2: " << s2.getData() << std::endl; // 输出 "s2: Hello"
    std::cout << "s1: " << (s1.getData() == nullptr ? "null" : s1.getData()) << std::endl; // 输出 "s1: null"
 
    MyString s3("World");
    s2 = std::move(s3); // 调用移动赋值运算符重载
    std::cout << "s2: " << s2.getData() << std::endl; // 输出 "s2: World"
    std::cout << "s3: " << (s3.getData() == nullptr ? "null" : s3.getData()) << std::endl; // 输出 "s3: null"
 
    return 0;
}

在这个示例中,我们定义了一个MyString类来管理字符串数据。该类有一个成员变量m_data指向字符串数据的内存空间,以及一个成员变量m_size表示字符串的长度。

为了支持移动语义,在类中定义了移动构造函数和移动赋值运算符重载函数。在移动构造函数中,我们将原有对象的资源所有权移交给新的对象,并将原有对象的m_data和m_size设为nullptr和0,以确保它们不会被析构函数释放。在移动赋值运算符重载函数中,我们先删除当前对象的指针成员变量,然后将右值对象的指针数据复制到当前对象中,再将右值对象的指针成员变量设为nullptr,以确保当前对象和右值对象独立管理各自的资源。

在main函数中,我们首先创建了一个MyString对象s1,然后通过调用std::move将其转移给另一个MyString对象s2。由于调用了移动构造函数,s2获得了s1的资源所有权,并将s1的指针成员变量设为nullptr。接着,我们通过调用std::move将另一个MyString对象s3的资源所有权转移到s2中,此时s2包含的字符串数据为"World"。最后,我们输出s1和s3的指针成员变量,可以看到它们都已经被设为nullptr。

通过这个示例,我们可以看到移动语义的使用方式,以及通过移动构造函数和移动赋值运算符重载实现资源所有权转移的方法。