程序员进阶:结构体深拷贝 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
总结
深拷贝和浅拷贝是编程中重要的概念,用于实现对象的拷贝操作。深拷贝通过复制构造函数在新对象中创建独立的数据拷贝,而浅拷贝只是复制引用或指针,导致多个对象共享相同的数据。在选择使用深拷贝或浅拷贝时,需要根据类的成员变量类型和拷贝需求进行权衡。深刻理解深拷贝和浅拷贝的概念和实现原理,有助于避免潜在的错误和内存管理问题,并提高程序的可靠性和性能。
热门推荐
小米电视色温调节全攻略:提升画质的关键设置
高清电视色温调节技巧大揭秘!
交通违法代码10872:擅自改装车辆将面临严厉处罚
裙带菜豆腐汤:一道营养丰富的家常美味
深入了解冠状动脉钙化,守护心脏健康
4个骨盆瑜伽体式,助你健康又美丽
凯格尔运动:让你的骨盆更健康!
医学生必看:骨盆解剖的重要性
瑞士球+BOSU球:骨盆稳定训练神器!
食品饮料供应链的挑战、趋势及创新应对策略
智慧农业崛起:四川绵阳三台县打造富裕新路径
五十岁女人别扮老,可以“复制”的穿搭思路,低调优雅、真体面!
曾国藩家训:家俭则兴,人勤则健
如何提升职业素养
全球首例!邯郸发现一例极罕见新血型,美国鉴定后收录并全球发布
新血型系统能降低输血风险|科普园地
王者荣耀光信最强出装和铭文搭配-人信最强出装铭文推荐
王者荣耀李信2025S38赛季出装铭文推荐:最强搭配与实战攻略
四丸之差:健脾丸、归脾丸、人参健脾丸与人参归脾丸的辨析
张雪峰解读军校毕业生发展路径:两条主线,多元选择
三九胃泰颗粒的适用人群有那些
胃病患者饮食指南:四招助你吃得饱又不伤胃
145亿,哪吒2海外一票难求,美国黄牛票炒到2万,上座率碾压美队4
康复治疗师提升竞争力全攻略:从认证到实践
2025年康复治疗师考试攻略:从考试大纲到备考技巧全解析
康复治疗师如何用心理学治愈你?
康复治疗师必备:RCF理论下的三大能力
薪酬福利增加46亿,顺丰激励机制给快递小哥提效又涨薪
百度和腾讯AI搜索大战,谁将引领未来?
中储粮:用科技创新守护大国粮仓