问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

程序员进阶:结构体深拷贝 vs 浅拷贝

创作时间:
2025-01-21 19:19:54
作者:
@小白创作中心

程序员进阶:结构体深拷贝 vs 浅拷贝

在编程的世界里,深拷贝和浅拷贝是两个经常被提及但又容易混淆的概念。它们在对象的复制过程中扮演着重要角色,理解它们的区别对于编写高效且无bug的代码至关重要。本文将带你深入了解深拷贝和浅拷贝的原理、实现方式以及应用场景,让你在编程的道路上更进一步。

01

深拷贝与浅拷贝的概念

深拷贝

深拷贝(Deep Copy)是指在拷贝对象时,会创建一个新的独立的对象,并复制原对象中的所有成员变量的值。深拷贝后的对象和原对象是完全独立的,修改一个对象不会影响另一个对象。

浅拷贝

浅拷贝(Shallow Copy)是指在拷贝对象时,只是复制了对象中的成员变量的值的引用或指针。浅拷贝后的对象和原对象共享一份数据,修改一个对象可能会影响另一个对象。

02

实现方式

C++中的实现

在C++中,深拷贝和浅拷贝主要通过复制构造函数来实现。

  • 深拷贝:通过自定义复制构造函数实现。在复制构造函数中,分配新的内存空间,并将原对象的值复制到新对象中。
class MyClass {
private:
    int* data;
    int size;

public:
    // 构造函数
    MyClass(int s) : size(s) {
        data = new int[size];
    }

    // 复制构造函数,实现深拷贝
    MyClass(const MyClass& other) : size(other.size) {
        data = new int[size];
        for (int i = 0; i < size; i++) {
            data[i] = other.data[i];
        }
    }
};
  • 浅拷贝:如果没有显式定义复制构造函数,C++会提供一个默认的复制构造函数,它执行的是浅拷贝。默认的复制构造函数将简单地将原对象的成员变量的值复制给新对象,导致新对象和原对象共享相同的数据。
class MyClass {
private:
    int* data;
    int size;

public:
    // 构造函数
    MyClass(int s) : size(s) {
        data = new int[size];
    }

    // 默认复制构造函数,执行浅拷贝
    // MyClass(const MyClass& other) = default;
};

C语言中的实现

在C语言中,深拷贝和浅拷贝需要手动编写代码来实现。

  • 浅拷贝:通过简单地将一个结构体或数组的成员值赋值给另一个结构体或数组来实现。这将导致两个对象共享相同的内存数据。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* name;
    int age;
} Person;

int main() {
    Person person1;
    person1.name = malloc(sizeof(char) * 10);
    strcpy(person1.name, "John");
    person1.age = 25;

    Person person2 = person1;  // 浅拷贝

    // 修改 person2 的值
    person2.name = malloc(sizeof(char) * 10);
    strcpy(person2.name, "Alice");
    person2.age = 30;

    // 输出 person1 和 person2 的值
    printf("person1: name=%s, age=%d\n", person1.name, person1.age);
    printf("person2: name=%s, age=%d\n", person2.name, person2.age);

    // 释放内存
    free(person1.name);
    free(person2.name);

    return 0;
}
  • 深拷贝:需要手动进行内存分配和数据复制。对于包含指针类型成员变量的结构体或数组,需要为每个指针类型的成员变量分配独立的内存空间,并将原始对象指针指向的数据复制到新分配的内存中。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* name;
    int age;
} Person;

// 深拷贝的函数
void deepCopyPerson(Person* dest, const Person* src) {
    dest->name = malloc(sizeof(char) * (strlen(src->name) + 1));
    strcpy(dest->name, src->name);
    dest->age = src->age;
}

int main() {
    Person person1;
    person1.name = malloc(sizeof(char) * 10);
    strcpy(person1.name, "John");
    person1.age = 25;

    Person person2;
    deepCopyPerson(&person2, &person1);  // 深拷贝

    // 修改 person2 的值
    free(person2.name);
    person2.name = malloc(sizeof(char) * 10);
    strcpy(person2.name, "Alice");
    person2.age = 30;

    // 输出 person1 和 person2 的值
    printf("person1: name=%s, age=%d\n", person1.name, person1.age);
    printf("person2: name=%s, age=%d\n", person2.name, person2.age);

    // 释放内存
    free(person1.name);
    free(person2.name);

    return 0;
}
03

使用场景

  • 深拷贝的使用场景:当类中包含指针成员变量时,需要确保每个对象都拥有独立的内存空间,以避免潜在的指针悬挂和内存泄漏问题。深拷贝可以用于复制动态分配的内存、复制其他资源等情况。

  • 浅拷贝的使用场景:当类中的成员变量是基本类型或没有指针成员变量时,浅拷贝可以提供更高效的拷贝操作,避免不必要的内存分配和复制开销。

04

代码示例

C++示例

#include <iostream>

class Person {
private:
    char* name;
    int age;

public:
    Person(const char* n, int a) {
        name = new char[strlen(n) + 1];
        strcpy(name, n);
        age = a;
    }

    // 浅拷贝构造函数
    Person(const Person& other) {
        name = other.name;
        age = other.age;
    }

    // 深拷贝构造函数
    Person(Person& other) {
        name = new char[strlen(other.name) + 1];
        strcpy(name, other.name);
        age = other.age;
    }

    void setName(const char* n) {
        delete[] name;
        name = new char[strlen(n) + 1];
        strcpy(name, n);
    }

    void print() {
        std::cout << "Name: " << name << ", Age: " << age << std::endl;
    }
};

int main() {
    Person p1("John", 25);
    Person p2 = p1;  // 浅拷贝
    Person p3(p1);   // 深拷贝

    p1.setName("Mike");

    p1.print();
    p2.print();
    p3.print();

    return 0;
}

C语言示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char* name;
    int age;
} Person;

// 浅拷贝函数
void shallowCopy(Person* dest, const Person* src) {
    dest->name = src->name;
    dest->age = src->age;
}

// 深拷贝函数
void deepCopy(Person* dest, const Person* src) {
    dest->name = malloc(strlen(src->name) + 1);
    strcpy(dest->name, src->name);
    dest->age = src->age;
}

int main() {
    Person person1;
    person1.name = malloc(10);
    strcpy(person1.name, "John");
    person1.age = 25;

    Person person2;
    shallowCopy(&person2, &person1);  // 浅拷贝

    Person person3;
    deepCopy(&person3, &person1);  // 深拷贝

    // 修改 person1 的值
    free(person1.name);
    person1.name = malloc(10);
    strcpy(person1.name, "Mike");
    person1.age = 30;

    // 输出 person1、person2 和 person3 的值
    printf("person1: name=%s, age=%d\n", person1.name, person1.age);
    printf("person2: name=%s, age=%d\n", person2.name, person2.age);
    printf("person3: name=%s, age=%d\n", person3.name, person3.age);

    // 释放内存
    free(person1.name);
    free(person2.name);
    free(person3.name);

    return 0;
}
05

总结

深拷贝和浅拷贝是编程中重要的概念,用于实现对象的拷贝操作。深拷贝通过复制构造函数在新对象中创建独立的数据拷贝,而浅拷贝只是复制引用或指针,导致多个对象共享相同的数据。在选择使用深拷贝或浅拷贝时,需要根据类的成员变量类型和拷贝需求进行权衡。深刻理解深拷贝和浅拷贝的概念和实现原理,有助于避免潜在的错误和内存管理问题,并提高程序的可靠性和性能。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号