如果你还不了解左值和右值,可以看 cpp中的lvalue和rvalue

我直接放代码了

#include <iostream>
#include <string>
 
 
void print(const std::string& str) {
    std::cout << str << std::endl;;
}
// 先写一个很蠢的string类,只是为了演示
class String {
private:
    char* data_;
    size_t size_;
public:
    String(const char* str) {
        print("default constructor of String");
        size_ = strlen(str);
        data_ = new char[size_];
        memcpy(data_, str, size_);
    }
 
    String(const String& other) {
        print("copy constructor of String");
        size_ = other.size_;
        data_ = new char[size_];
        memcpy(data_, other.data_, size_);
    }
    String(String&& other) noexcept {
        print("move constructor of String");
        //我们在这里偷走了other的资源。
        size_ = other.size_;
        data_ = other.data_;
 
        other.data_ = nullptr;
        other.size_ = 0;
    }
    ~String() {
        print("Destroy String!");
        delete data_;
    }
    void Print() const {
        for (int i = 0;i < size_; i++)
            printf("%c", data_[i]);
    }
};
 
class A {
private:
    String a;
public:
    A(const String& str):a(str) {
        print("default constructor of A");
    }
    // 如果不在这里做这个看似很蠢的cast,那么String的拷贝构造函数仍然会被调用。
    A(String&& str):a(static_cast<String&&>(str)) {
        print("move string constructor of A");
    }
};
 
 
int main(int argc, char* argv[]) {
    A a(String("test"));
    return 0;
    /*
     * output:
     *        default constructor of String
     *        move constructor of String
     *        move string constructor of A
     *        Destroy String!
     *        Destroy String!
     */
}
 

= and std::move

还记得吗,上一段中我们写了类似 static_cast<String&&>(str) 这样的东西,更优雅的方式是使用 std::move(), 不仅优雅哈哈而且还更容易理解。

最后,如果我们实现了下面这个函数

String& operator=(String&& other) noexcept {
    print("move constructor of String");
    //我们在这里偷走了other的资源。
    if (this != other) {//如果两个东西是同一个东西,就没必要做任何操作了
        delete[] data_;
        size_ = other.size_;
        data_ = other.data_;
 
        other.data_ = nullptr;
        other.size_ = 0;
    }
    return *this;
}

我们就可以做这样的事情

String a("apple");
String b;
b = std::move(a); //这里会直接调用 move operator =
Sting c = std::move(b); //这里则会调用 move constructor
//b将窃取a的资源

:::danger 这里还要一个关于 cpp中的五三零规则需要考虑 :::