C++11的移动语义
C++11引入了移动语义,这是一种用于优化对象拷贝操作的机制。传统的拷贝构造函数和赋值操作符会对对象进行完全的复制,但有时候我们并不需要完全的复制,只需要把对象的资源所有权转移给另一个对象即可。
移动语义通过使用右值引用(&&)来实现。右值引用表示一个将要被销毁的临时对象或者一个可以被转移所有权的对象。移动构造函数和移动赋值操作符可以接受右值引用作为参数,并且可以将对象的内部资源指针转移给另一个对象,而不需要进行复制。当对象的数据成员是动态分配的内存时,使用移动语义可以显著提高性能和效率。
下面是一个例子,演示如何使用移动语义:
#include <iostream>
#include <string>
using namespace std;
class MyString {
public:
MyString() : mData(nullptr), mSize(0) {}
MyString(const char* data) : mData(nullptr), mSize(0) {
mSize = strlen(data);
mData = new char[mSize + 1];
memcpy(mData, data, mSize);
}
MyString(const MyString &other) : mData(nullptr), mSize(0) {
mSize = other.mSize;
mData = new char[mSize + 1];
memcpy(mData, other.mData, mSize);
}
MyString(MyString &&other) : mData(other.mData), mSize(other.mSize) {
other.mData = nullptr;
other.mSize = 0;
}
~MyString() {
delete[] mData;
}
MyString& operator=(const MyString &other) {
if (this != &other) {
delete[] mData;
mSize = other.mSize;
mData = new char[mSize + 1];
memcpy(mData, other.mData, mSize);
}
return *this;
}
MyString& operator=(MyString &&other) {
if (this != &other) {
delete[] mData;
mData = other.mData;
mSize = other.mSize;
other.mData = nullptr;
other.mSize = 0;
}
return *this;
}
const char* data() const { return mData; }
size_t size() const { return mSize; }
private:
char *mData;
size_t mSize;
};
int main() {
MyString str1("Hello World");
MyString str2 = std::move(str1);
cout << "str1: " << str1.data() << ", size: " << str1.size() << endl;
cout << "str2: " << str2.data() << ", size: " << str2.size() << endl;
MyString str3;
str3 = std::move(str2);
cout << "str2: " << str2.data() << ", size: " << str2.size() << endl;
cout << "str3: " << str3.data() << ", size: " << str3.size() << endl;
return 0;
}
输出结果:
str1: , size: 0
str2: Hello World, size: 11
str2: , size: 0
str3: Hello World, size: 11
在这个例子中,我们定义了一个简单的字符串类,并实现了它的移动构造函数和移动赋值操作符。我们用一个带有字符串数据的对象来初始化对象str1
,然后通过std::move()
函数把它的内部资源转移到了对象str2
中。
然后,我们再次使用std::move()
函数把str2
的内部资源转移到了str3
,这样就删除了str2
中的数据。最后,我们打印了所有对象的原始数据以及大小,可以看到移动语义成功地将内部资源的所有权转移给了另一个对象,而不需要进行复制。