MST

星途 面试题库

面试题:C++ 移动语义与深拷贝浅拷贝的关系

深入分析 C++ 移动语义与传统深拷贝、浅拷贝之间的联系与区别,结合代码示例说明移动语义如何在避免深拷贝开销的同时保证数据的正确处理。
22.2万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

深拷贝、浅拷贝与移动语义的联系与区别

1. 浅拷贝

浅拷贝是指在对象复制时,只复制对象中指针的值,而不复制指针所指向的内存空间。这意味着多个对象的指针指向同一块内存区域。如果其中一个对象释放了这块内存,其他对象的指针就会变成野指针,导致程序出现未定义行为。

2. 深拷贝

深拷贝是指在对象复制时,不仅复制对象中指针的值,还会为指针重新分配内存,并将原指针所指向的内存内容复制到新分配的内存中。这样每个对象都有自己独立的内存区域,避免了野指针问题,但深拷贝的开销较大,因为每次复制都需要重新分配内存并进行数据复制。

3. 移动语义

移动语义是 C++11 引入的新特性,它允许将资源(如动态分配的内存)从一个对象转移到另一个对象,而不是进行传统的深拷贝。这样可以避免不必要的内存分配和数据复制,提高程序性能。移动语义通过 std::move 函数实现,它将左值转换为右值引用,从而触发移动构造函数或移动赋值运算符。

代码示例

#include <iostream>
#include <memory>

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 = strlen(str);
            data = new char[length + 1];
            strcpy(data, str);
        }
    }

    // 析构函数
    ~MyString() {
        delete[] data;
    }

    // 拷贝构造函数(深拷贝)
    MyString(const MyString& other) {
        length = other.length;
        data = new char[length + 1];
        strcpy(data, other.data);
    }

    // 拷贝赋值运算符(深拷贝)
    MyString& operator=(const MyString& other) {
        if (this != &other) {
            delete[] data;
            length = other.length;
            data = new char[length + 1];
            strcpy(data, other.data);
        }
        return *this;
    }

    // 移动构造函数
    MyString(MyString&& other) noexcept {
        data = other.data;
        length = other.length;
        other.data = nullptr;
        other.length = 0;
    }

    // 移动赋值运算符
    MyString& operator=(MyString&& other) noexcept {
        if (this != &other) {
            delete[] data;
            data = other.data;
            length = other.length;
            other.data = nullptr;
            other.length = 0;
        }
        return *this;
    }

    void print() const {
        std::cout << data << std::endl;
    }
};

int main() {
    MyString str1("Hello, World!");
    MyString str2 = str1; // 调用拷贝构造函数(深拷贝)
    MyString str3 = std::move(str1); // 调用移动构造函数

    str2.print();
    str3.print();

    return 0;
}

在上述代码中:

  • 深拷贝:拷贝构造函数和拷贝赋值运算符会为新对象重新分配内存,并复制数据,确保每个对象都有独立的内存。
  • 移动语义:移动构造函数和移动赋值运算符将资源从源对象转移到目标对象,源对象被置为空,避免了深拷贝的开销。

通过使用移动语义,在某些场景下(如函数返回临时对象),可以显著提高程序性能,同时保证数据的正确处理。