MST

星途 面试题库

面试题:C++中深拷贝与浅拷贝在拷贝构造函数性能方面的差异

在C++中,深拷贝和浅拷贝是两种常见的拷贝方式。请详细阐述深拷贝构造函数和浅拷贝构造函数在性能上的不同表现,在何种场景下应选择深拷贝,何种场景下应选择浅拷贝,并且通过代码示例说明这两种拷贝构造函数的实现及其性能差异。
12.8万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

深拷贝和浅拷贝在性能上的不同表现

  1. 浅拷贝
    • 性能优势:浅拷贝只是简单地复制对象的成员变量,对于指针类型的成员变量,只是复制指针的值(即地址),不复制指针所指向的内存空间。因此,浅拷贝的执行速度非常快,因为它没有额外的内存分配和数据复制操作。
    • 性能劣势:由于多个对象共享同一块内存,当其中一个对象释放这块内存时,其他对象的指针就会变成野指针,可能导致程序崩溃。而且如果对象中有动态分配的内存,对共享内存的修改会影响到所有指向该内存的对象,不符合某些需求场景。
  2. 深拷贝
    • 性能劣势:深拷贝需要为新对象分配独立的内存空间,并将原对象中指针所指向的内存中的数据逐字节复制到新分配的内存中。这涉及到额外的内存分配和数据复制操作,因此性能开销较大,尤其是当对象包含大量数据时。
    • 性能优势:每个对象都有自己独立的内存空间,修改一个对象的数据不会影响其他对象,数据安全性和独立性更好,适用于需要对象间数据相互隔离的场景。

选择深拷贝和浅拷贝的场景

  1. 选择浅拷贝的场景
    • 当对象的成员变量不包含动态分配的内存,或者多个对象可以安全地共享同一块内存时,适合使用浅拷贝。例如,简单的结构体或类,其成员变量都是基本数据类型(如 intfloat 等)或者 std::stringstd::string 内部已经处理了内存管理,浅拷贝 std::string 成员是安全的)。
  2. 选择深拷贝的场景
    • 当对象包含动态分配的内存,并且需要每个对象都有自己独立的内存副本,互不影响时,必须使用深拷贝。比如,一个类中包含一个指针成员,指向动态分配的数组或其他复杂数据结构,为了保证每个对象的独立性,就需要深拷贝。

代码示例

#include <iostream>
#include <cstring>

class ShallowCopy {
public:
    ShallowCopy(int size) {
        this->size = size;
        data = new int[size];
    }
    // 浅拷贝构造函数
    ShallowCopy(const ShallowCopy& other) {
        size = other.size;
        data = other.data;
    }
    ~ShallowCopy() {
        delete[] data;
    }
private:
    int* data;
    int size;
};

class DeepCopy {
public:
    DeepCopy(int size) {
        this->size = size;
        data = new int[size];
    }
    // 深拷贝构造函数
    DeepCopy(const DeepCopy& other) {
        size = other.size;
        data = new int[size];
        std::memcpy(data, other.data, size * sizeof(int));
    }
    ~DeepCopy() {
        delete[] data;
    }
private:
    int* data;
    int size;
};

int main() {
    // 浅拷贝性能测试
    {
        ShallowCopy shallow1(1000000);
        auto start = std::chrono::high_resolution_clock::now();
        ShallowCopy shallow2(shallow1);
        auto end = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
        std::cout << "浅拷贝耗时: " << duration << " 微秒" << std::endl;
    }
    // 深拷贝性能测试
    {
        DeepCopy deep1(1000000);
        auto start = std::chrono::high_resolution_clock::now();
        DeepCopy deep2(deep1);
        auto end = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
        std::cout << "深拷贝耗时: " << duration << " 微秒" << std::endl;
    }
    return 0;
}

在上述代码中:

  • ShallowCopy 类实现了浅拷贝构造函数,只是简单复制指针。
  • DeepCopy 类实现了深拷贝构造函数,为新对象分配内存并复制数据。
  • main 函数中,通过 std::chrono 库对浅拷贝和深拷贝进行性能测试,可以明显看到深拷贝由于有内存分配和数据复制操作,耗时比浅拷贝要长(具体时长取决于机器性能和数据量大小)。