MST

星途 面试题库

面试题:C++默认拷贝构造函数的深拷贝与浅拷贝问题

当C++编译器自动生成拷贝构造函数时,通常执行的是浅拷贝。请解释浅拷贝可能带来的问题,并举例说明如何在类中自定义拷贝构造函数实现深拷贝,以避免这些问题。同时说明在什么情况下深拷贝是必要的。
38.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

浅拷贝可能带来的问题

  1. 内存重复释放:当类中包含动态分配的内存(如通过new分配的指针成员),浅拷贝只是简单地复制指针的值,而不是复制指针所指向的内存。这就导致两个对象的指针指向同一块内存,当其中一个对象析构释放内存时,另一个对象的指针就变成了野指针,再次访问或析构时会导致程序崩溃。
  2. 数据修改相互影响:由于两个对象的指针指向同一块内存,对其中一个对象的数据修改会影响到另一个对象,这可能导致逻辑错误。

自定义拷贝构造函数实现深拷贝示例

#include <iostream>
#include <cstring>

class MyString {
private:
    char* str;
    int length;
public:
    // 构造函数
    MyString(const char* s = nullptr) {
        if (s == nullptr) {
            length = 0;
            str = new char[1];
            str[0] = '\0';
        }
        else {
            length = strlen(s);
            str = new char[length + 1];
            strcpy(str, s);
        }
    }

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

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

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

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

int main() {
    MyString s1("Hello");
    MyString s2(s1); // 使用自定义拷贝构造函数
    s1.print();
    s2.print();

    s2 = MyString("World"); // 使用重载的赋值运算符
    s1.print();
    s2.print();

    return 0;
}

深拷贝必要的情况

  1. 类中包含动态分配的资源:如上述MyString类中动态分配了字符数组,如果不进行深拷贝,多个对象共享同一块动态内存会带来问题。
  2. 对象内部状态需要独立管理:当对象的某个成员代表一种需要独立拥有的资源(如文件句柄、网络连接等),为了每个对象对该资源的操作不相互干扰,需要深拷贝来确保每个对象有自己独立的资源副本。