MST

星途 面试题库

面试题:C++赋值运算符常见问题之高级难度

假设有一个复杂的C++类,它包含指针成员变量指向动态分配的内存,同时涉及到继承体系。请详细阐述在进行赋值运算符重载时,需要考虑哪些关键因素以避免内存泄漏、悬空指针等问题,并写出实现代码。
42.0万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

关键因素

  1. 自我赋值检查:在赋值运算符重载函数内部,首先要检查是否是自我赋值。如果是自我赋值,直接返回*this,避免不必要的内存释放和重新分配。
  2. 释放旧资源:在为对象分配新的内存之前,需要释放对象当前已有的动态分配的内存,以防止内存泄漏。
  3. 深拷贝:由于指针成员变量指向动态分配的内存,在赋值时需要进行深拷贝,即分配新的内存并将源对象指针指向的内容复制到新分配的内存中。
  4. 处理继承体系:如果涉及继承体系,需要先调用基类的赋值运算符重载函数,以正确处理基类部分的成员变量。

实现代码

#include <iostream>
#include <cstring>

// 基类
class Base {
public:
    Base() : data(nullptr), length(0) {}
    Base(const char* str) {
        if (str) {
            length = std::strlen(str);
            data = new char[length + 1];
            std::strcpy(data, str);
        } else {
            length = 0;
            data = nullptr;
        }
    }
    Base(const Base& other) {
        length = other.length;
        if (other.data) {
            data = new char[length + 1];
            std::strcpy(data, other.data);
        } else {
            data = nullptr;
        }
    }
    Base& operator=(const Base& other) {
        if (this == &other) {
            return *this;
        }
        delete[] data;
        length = other.length;
        if (other.data) {
            data = new char[length + 1];
            std::strcpy(data, other.data);
        } else {
            data = nullptr;
        }
        return *this;
    }
    ~Base() {
        delete[] data;
    }
private:
    char* data;
    size_t length;
};

// 派生类
class Derived : public Base {
public:
    Derived() : extraData(nullptr) {}
    Derived(const char* str, const char* extra) : Base(str) {
        if (extra) {
            extraLength = std::strlen(extra);
            extraData = new char[extraLength + 1];
            std::strcpy(extraData, extra);
        } else {
            extraLength = 0;
            extraData = nullptr;
        }
    }
    Derived(const Derived& other) : Base(other) {
        extraLength = other.extraLength;
        if (other.extraData) {
            extraData = new char[extraLength + 1];
            std::strcpy(extraData, other.extraData);
        } else {
            extraData = nullptr;
        }
    }
    Derived& operator=(const Derived& other) {
        if (this == &other) {
            return *this;
        }
        Base::operator=(other); // 调用基类赋值运算符
        delete[] extraData;
        extraLength = other.extraLength;
        if (other.extraData) {
            extraData = new char[extraLength + 1];
            std::strcpy(extraData, other.extraData);
        } else {
            extraData = nullptr;
        }
        return *this;
    }
    ~Derived() {
        delete[] extraData;
    }
private:
    char* extraData;
    size_t extraLength;
};