程序员进阶:结构体深拷贝 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
总结
深拷贝和浅拷贝是编程中重要的概念,用于实现对象的拷贝操作。深拷贝通过复制构造函数在新对象中创建独立的数据拷贝,而浅拷贝只是复制引用或指针,导致多个对象共享相同的数据。在选择使用深拷贝或浅拷贝时,需要根据类的成员变量类型和拷贝需求进行权衡。深刻理解深拷贝和浅拷贝的概念和实现原理,有助于避免潜在的错误和内存管理问题,并提高程序的可靠性和性能。
热门推荐
中国心血管病患病情况及基因检测的重要性
电信话费一分钟多少钱?
中国女人化妆的秘诀是什么?如何让妆容更自然?
职场高情商话术公式:热情,大方,一问三不知!
DHCP协议详解:定义、配置与故障排查
“接亲加价18万彩礼”反转?非现场加价,原来的彩礼没给到父母
工业硅期权合约的用途有哪些?能对冲工业硅期货吗?
测量血压前,为什么必须安静坐一会儿?
生活动态文案创作指南:捕捉瞬间,传递情感与智慧
CNC编程要学什么软件
班主任视角下的中西面点技艺培养与文化传承
资阳人对待“冬至”的仪式感有多强?一碗羊肉汤“搅热”市场
血糖引起的并发症挂什么科
从《人类简史》到《智人之上》:尤瓦尔·赫拉利的思想轨迹和文明史观
从《人类简史》到《智人之上》:尤瓦尔·赫拉利的思想轨迹和文明史观
社交恐惧症的三大解决方案:从心理治疗到自我调节
宋江的真实历史:北宋农民起义首领的短暂抗争
美国时间与北京时间存在哪些差异和换算方法?
粉丝1400万网红没赚钱反负债150万元 坚持不接广告的「羞耻」
南北饮食文化的明珠:汤圆与元宵的全方位对比
玫瑰的寓意与象征意义(探索玫瑰背后的寓意与象征)
路边停车位收费合法吗?员工上下班途中骑车摔伤算工伤吗?
7:17.55,雅各布破3000米世界纪录 | 背后的训练给跑者带来的启示...
广州中等职业教育质量报告发布 去年中职生升学率超64%
肠鸣多屁是什么原因
优秀PPT工作总结的步骤与技巧分享
老司机14年经验谈:自驾游车型选择攻略
象山红美人:中国柑橘产业的破局之道
玉镯和红绳戴在哪只手:左右手的选择与搭配建议
工程审计流程规范化怎么优化?