基于右值引用可以实现移动语义的特性。

#include <iostream>
#include <string>
#include <cstring>

class MyString {
public:
    MyString() : data_(nullptr), size_(0) {}
    MyString(const char* str) : data_(new char[strlen(str) + 1]), size_(strlen(str)) {
        strcpy(data_, str);
        std::cout << "normal construct func" << std::endl;
    }
    MyString(const MyString& other) : data_(new char[other.size_ + 1]), size_(other.size_) {
        strcpy(data_, other.data_);
        std::cout << "copy construct func" << std::endl;
    }
    MyString(MyString&& other) : data_(other.data_), size_(other.size_) {
        other.data_ = nullptr;
        other.size_ = 0;
        std::cout << "move construct func" << std::endl;
    }
    ~MyString() {
        delete[] data_;
    }
    MyString& operator=(const MyString& other) {
        if (this != &other) {
            delete[] data_;
            data_ = new char[other.size_ + 1];
            size_ = other.size_;
            strcpy(data_, other.data_);
        }
        std::cout << "copy assign func" << std::endl;
        return *this;
    }
    MyString& operator=(MyString&& other) {
        if (this != &other) {
            delete[] data_;
            data_ = other.data_;
            size_ = other.size_;
            other.data_ = nullptr;
            other.size_ = 0;
        }
        std::cout << "move assign func" << std::endl;
        return *this;
    }
    const char* c_str() const {
        return data_;
    }
private:
    char* data_;
    size_t size_;
};

int main() {
    MyString s1("Hello");
    MyString s2("world");
    MyString s3 = s1;
    MyString s4 = std::move(s2);
    std::cout << s1.c_str() << " " << s3.c_str() << " " << s4.c_str() << std::endl;
    return 0;
}

在这个示例代码中,我们定义了一个名为 MyString 的类,它表示一个字符串。这个类有一个指向字符数组的指针 data_ 和一个表示字符串长度的变量 size_。它还实现了默认构造函数、带有 const char* 参数的构造函数、拷贝构造函数、移动构造函数、拷贝赋值运算符、移动赋值运算符和析构函数。

这个示例代码演示了移动语义的用法。通过移动对象而不是拷贝对象,可以提高程序的性能。在 MyString 类中,我们使用了移动构造函数和移动赋值运算符来实现移动语义。

int main() {
    MyString s1("Hello");
    MyString s2("world");
    MyString s3;
    MyString s4;
    s3 = s1;
    s4 = std::move(s2);
    std::cout << s1.c_str() << " " << s3.c_str() << " " << s4.c_str() << std::endl;
    return 0;
}

如果我们使用拷贝构造函数或拷贝赋值运算符来初始化或赋值对象,那么就会触发拷贝构造函数或拷贝赋值运算符。这些操作会创建一个新的对象并拷贝原始对象的值,而不是转移资源所有权。因此,拷贝构造函数和拷贝赋值运算符会比移动构造函数和移动赋值运算符更慢,特别是当对象的资源很大时。