MST

星途 面试题库

面试题:C++ 赋值运算符与拷贝构造函数的深度应用考查

假设有一个自定义类 `MyClass`,包含一个动态分配的数组成员变量。请分别实现其拷贝构造函数和赋值运算符重载,确保深拷贝且处理自我赋值情况,说明实现过程中的关键要点和可能出现的错误。
43.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 定义 MyClass

#include <iostream>
#include <cstring>

class MyClass {
private:
    int* data;
    int size;
public:
    // 构造函数
    MyClass(int s) : size(s) {
        data = new int[size];
        for (int i = 0; i < size; ++i) {
            data[i] = 0;
        }
    }

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

    // 拷贝构造函数
    MyClass(const MyClass& other) : size(other.size) {
        data = new int[size];
        std::memcpy(data, other.data, size * sizeof(int));
    }

    // 赋值运算符重载
    MyClass& operator=(const MyClass& other) {
        if (this == &other) {
            return *this;
        }
        delete[] data;
        size = other.size;
        data = new int[size];
        std::memcpy(data, other.data, size * sizeof(int));
        return *this;
    }
};

2. 关键要点

  • 拷贝构造函数
    • 分配新的内存空间,大小与源对象相同,即 data = new int[size];
    • 使用 std::memcpy 或循环逐个复制元素,将源对象的数据成员 data 中的内容复制到新分配的内存中。这里使用 std::memcpy(data, other.data, size * sizeof(int));
  • 赋值运算符重载
    • 首先检查自我赋值情况,即 if (this == &other)。如果是自我赋值,直接返回当前对象 return *this;
    • 释放当前对象已分配的内存 delete[] data;
    • 分配新的内存空间,并设置大小 size = other.size; data = new int[size];
    • 复制源对象的数据到新分配的内存中 std::memcpy(data, other.data, size * sizeof(int));
    • 返回当前对象引用 return *this;,以支持链式赋值。

3. 可能出现的错误

  • 内存泄漏
    • 在赋值运算符重载中,如果忘记释放当前对象已分配的内存 delete[] data;,会导致内存泄漏,因为新的内存分配后,旧的内存就无法再访问和释放了。
  • 未处理自我赋值
    • 如果在赋值运算符重载中没有检查自我赋值情况,直接释放内存并重新分配,会导致在自我赋值时对象的数据被破坏,因为释放内存后再从同一个对象复制数据就会出错。
  • 浅拷贝问题
    • 如果拷贝构造函数或赋值运算符重载只是简单地复制指针,而不是分配新内存并复制数据,就会出现浅拷贝问题。多个对象将共享同一块内存,当一个对象析构释放内存后,其他对象的指针就会成为野指针,访问这些野指针会导致未定义行为。