MST

星途 面试题库

面试题:C++重写拷贝构造函数时内存管理与性能优化

假设你正在开发一个大型的C++项目,其中有一个类包含大量的数据成员,包括动态分配的内存。当重写这个类的拷贝构造函数时,如何通过合理的内存管理策略来优化性能?例如,如何避免不必要的内存分配和释放,以及如何利用移动语义来提高效率。请详细说明你的思路,并给出相应的代码示例。
12.8万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 思路
    • 避免不必要的内存分配和释放
      • 对于动态分配的内存,如果源对象和目标对象可以共享这块内存,那么可以采用“拷贝指针,引用计数”的策略。这样在拷贝时,只是复制指针和增加引用计数,而不是重新分配内存。当对象析构时,如果引用计数为0才释放内存。
    • 利用移动语义提高效率
      • 移动构造函数是为了在对象所有权转移时避免不必要的内存拷贝。当一个对象处于即将销毁的状态(如函数返回临时对象),可以将其资源“移动”到新对象,而不是复制。这意味着源对象的资源指针被转移到目标对象,源对象的指针被置为nullptr,从而避免了内存重新分配。
  2. 代码示例
#include <iostream>
#include <memory>

class BigData {
private:
    int* data;
    std::size_t size;
    std::size_t* refCount;
public:
    // 构造函数
    BigData(std::size_t s) : size(s) {
        data = new int[size];
        refCount = new std::size_t(1);
    }

    // 拷贝构造函数
    BigData(const BigData& other) : size(other.size), data(other.data), refCount(other.refCount) {
        (*refCount)++;
    }

    // 移动构造函数
    BigData(BigData&& other) noexcept : size(other.size), data(other.data), refCount(other.refCount) {
        other.data = nullptr;
        other.refCount = nullptr;
        other.size = 0;
    }

    // 析构函数
    ~BigData() {
        if (refCount && --(*refCount) == 0) {
            delete[] data;
            delete refCount;
        }
    }

    // 赋值运算符重载
    BigData& operator=(const BigData& other) {
        if (this == &other) {
            return *this;
        }
        if (refCount && --(*refCount) == 0) {
            delete[] data;
            delete refCount;
        }
        size = other.size;
        data = other.data;
        refCount = other.refCount;
        (*refCount)++;
        return *this;
    }

    // 移动赋值运算符重载
    BigData& operator=(BigData&& other) noexcept {
        if (this == &other) {
            return *this;
        }
        if (refCount && --(*refCount) == 0) {
            delete[] data;
            delete refCount;
        }
        size = other.size;
        data = other.data;
        refCount = other.refCount;
        other.data = nullptr;
        other.refCount = nullptr;
        other.size = 0;
        return *this;
    }
};

class MyLargeClass {
private:
    BigData bigData;
    // 其他数据成员
public:
    MyLargeClass(std::size_t s) : bigData(s) {}

    // 拷贝构造函数利用BigData的拷贝构造优化
    MyLargeClass(const MyLargeClass& other) : bigData(other.bigData) {
        // 对于其他数据成员进行常规拷贝
    }

    // 移动构造函数利用BigData的移动构造优化
    MyLargeClass(MyLargeClass&& other) noexcept : bigData(std::move(other.bigData)) {
        // 对于其他数据成员进行常规移动(如果有的话)
    }
};