面试题答案
一键面试移动语义优化拷贝构造函数性能简述
在 C++ 中,拷贝构造函数会完整地复制对象的内容,这对于包含动态分配内存的对象来说,开销较大。移动语义允许将资源(如动态分配的内存)从一个对象转移到另一个对象,而不是进行深度复制。这样可以避免不必要的内存分配和释放操作,从而提升性能。具体来说,移动构造函数通过 “窃取” 源对象的资源,而不是复制资源,来创建新对象,使得源对象处于可析构的状态(通常是将源对象的指针置为 nullptr
等操作)。
包含动态内存分配的类及相关构造函数实现
#include <iostream>
#include <cstring>
class MyString {
private:
char* data;
size_t length;
public:
// 构造函数
MyString(const char* str = nullptr) {
if (str == nullptr) {
length = 0;
data = new char[1];
data[0] = '\0';
} else {
length = std::strlen(str);
data = new char[length + 1];
std::strcpy(data, str);
}
}
// 拷贝构造函数
MyString(const MyString& other) {
length = other.length;
data = new char[length + 1];
std::strcpy(data, other.data);
}
// 移动构造函数
MyString(MyString&& other) noexcept {
data = other.data;
length = other.length;
other.data = nullptr;
other.length = 0;
}
// 析构函数
~MyString() {
delete[] data;
}
// 重载赋值运算符
MyString& operator=(const MyString& other) {
if (this == &other) {
return *this;
}
delete[] data;
length = other.length;
data = new char[length + 1];
std::strcpy(data, other.data);
return *this;
}
// 重载移动赋值运算符
MyString& operator=(MyString&& other) noexcept {
if (this == &other) {
return *this;
}
delete[] data;
data = other.data;
length = other.length;
other.data = nullptr;
other.length = 0;
return *this;
}
void print() const {
std::cout << data << std::endl;
}
};
移动构造函数避免不必要内存复制的说明
在上述 MyString
类的移动构造函数中,并没有像拷贝构造函数那样重新分配内存并复制数据。而是直接将源对象 other
的 data
指针和 length
成员变量接管过来,然后将 other
的 data
指针置为 nullptr
,length
设为 0。这样,新对象就拥有了源对象的资源,而源对象处于一个可析构的状态(释放 nullptr
不会有问题)。避免了重新分配内存和复制数据的操作,从而提升了性能。例如,当使用移动构造函数从一个临时对象创建新对象时,无需进行深度复制,大大提高了效率。