MST

星途 面试题库

面试题:C++ 中拷贝构造函数内存管理的基础问题

请简述在C++中,拷贝构造函数何时会被调用?并且说明在拷贝构造函数内部,对于动态分配内存的成员变量,通常应该如何进行内存管理以避免内存泄漏?
14.3万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 拷贝构造函数的调用时机
    • 对象初始化:当用一个已有的对象来初始化同类型的新对象时,拷贝构造函数会被调用。例如:
    class MyClass {
    public:
        MyClass() {}
        MyClass(const MyClass& other) {}
    };
    MyClass obj1;
    MyClass obj2 = obj1; // 这里调用拷贝构造函数
    
    • 函数参数传递:当对象作为参数按值传递给函数时,会调用拷贝构造函数创建一个临时对象。例如:
    void func(MyClass obj) {
        // 函数体
    }
    MyClass obj;
    func(obj); // 这里为参数传递调用拷贝构造函数
    
    • 函数返回对象:当函数按值返回一个对象时,会调用拷贝构造函数创建一个临时对象作为返回值。例如:
    MyClass func() {
        MyClass obj;
        return obj; // 这里调用拷贝构造函数返回对象
    }
    MyClass result = func();
    
  2. 动态分配内存成员变量的内存管理
    • 深拷贝:在拷贝构造函数内部,对于动态分配内存的成员变量,不能简单地进行指针赋值(浅拷贝),否则会导致多个对象指向同一块内存,在析构时出现重复释放内存的错误。应该重新分配内存,并将源对象动态分配内存中的数据复制到新分配的内存中。例如:
    class MyClass {
    private:
        int* data;
    public:
        MyClass() {
            data = new int(0);
        }
        MyClass(const MyClass& other) {
            data = new int(*other.data); // 重新分配内存并复制数据
        }
        ~MyClass() {
            delete data;
        }
    };
    
    • 使用智能指针:现代C++可以使用智能指针(如std::unique_ptrstd::shared_ptr)来管理动态分配的内存,这样可以自动处理内存释放,避免手动管理内存带来的泄漏风险。例如:
    #include <memory>
    class MyClass {
    private:
        std::unique_ptr<int> data;
    public:
        MyClass() : data(std::make_unique<int>(0)) {}
        MyClass(const MyClass& other) : data(std::make_unique<int>(*other.data)) {}
    };
    
    这里std::unique_ptr会在对象销毁时自动释放其所管理的内存,从而避免内存泄漏。