網站首頁 編程語言 正文
淺拷貝
C語言中的淺拷貝是指在拷貝過程中,對于指針型成員變量只拷貝指針本身,而不拷貝指針所指向的目標,它按字節復制的。我們分幾種情況舉例子來看一下。
結構體中不存在指針成員變量時
代碼如下:
#include <stdio.h>
typedef struct {
char name[64];
int age;
}Member;
int main(){
Member stu1 = { "LiMing", 18 };
Member stu2;
stu2 = stu1;
printf("%s,%d\n", stu2.name, stu2.age);
system("pause");
return 0;
}
運行如下:
結構體中存在指針成員變量時
代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
int age;
}Member;
int main() {
Member Member1, Member2;
Member1.name = malloc(sizeof(char) * 64);
if (NULL == Member1.name)
{
printf("malloc failed\n");
}
memset(Member1.name, 0, 64);
//strcpy(Member1.name, "LiMing");
snprintf(Member1.name, 64, "LiMing");
Member1.age = 18;
Member2 = Member1;/*拷貝*/
snprintf(Member2.name, 64, "LiXiaoYao");
Member2.age = 29;
printf("%s, %d\n", Member1.name, Member1.age);
if (NULL != Member1.name) {
free(Member1.name);
Member1.name = NULL;
}
system("pause");
return 0;
}
運行如下:
從中我們看到,改變Member2的值,Member1的值也改變了,這說明一片空間被兩個不同的子對象共享了,改變一個對象的值另外一個也會隨之改變。
我們改變Member2寫法,申請內存的代碼如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
int age;
}Member;
int main() {
Member Member1;
Member1.name = malloc(sizeof(char) * 64);
if (NULL == Member1.name)
{
printf("malloc failed\n");
}
memset(Member1.name, 0, 64);
//strcpy(Member1.name, "LiMing");
snprintf(Member1.name, 64, "LiMing");
Member1.age = 18;
Member Member2;
Member2.name = malloc(sizeof(char) * 64);
if (NULL == Member2.name)
{
printf("malloc failed\n");
}
memset(Member2.name, 0, 64);
//strcpy(Member2.name, "LiMing");
snprintf(Member2.name, 64, "LiXiaoYao");
Member2.age = 29;
Member1 = Member2;
printf("%s, %d\n", Member2.name, Member2.age);
if (NULL != Member1.name) {
free(Member1.name);
Member1.name = NULL;
}
if (NULL != Member2.name) {
free(Member2.name);
Member2.name = NULL;
}
system("pause");
return 0;
}
運行如下:
從中我們看到,當數據成員中有指針時,兩個類中的兩個指針將指向同一個地址,當對象快結束時,會調用兩次free函數,此時Member2已經是野指針(圖中有X的錯誤標志),這個野指針指向的內存空間已經被釋放掉,再次釋放會報異常錯誤,要解決這個問題就要涉及到深拷貝了。
深拷貝
深拷貝除了拷貝其成員本身的值之外,還拷貝成員指向的動態內存區域內容,深拷貝會在堆內存中另外申請空間來儲存數據。
解決的思路是在釋放掉被賦值指針變量的舊指向內存時,重新對其開辟新內存,這種情況下兩個結構體中指針地址不同,但是指向的內容是一致的。代碼如下:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *name;
int age;
}Member;
int main() {
Member Member1;
Member1.name = malloc(sizeof(char) * 64);
if (NULL == Member1.name)
{
printf("malloc failed\n");
}
memset(Member1.name, 0, 64);
//strcpy(Member1.name, "LiMing");
snprintf(Member1.name, 64, "LiMing");
Member1.age = 18;
Member Member2;
Member2.name = malloc(sizeof(char) * 64);
if (NULL == Member2.name)
{
printf("malloc failed\n");
}
memset(Member2.name, 0, 64);
//strcpy(Member2.name, "LiMing");
snprintf(Member2.name, 64, "LiXiaoYao");
Member2.age = 29;
if (Member1.name != NULL) {
free(Member1.name);
Member1.name = NULL;
}
Member1.name = malloc(strlen(Member2.name) + 1);
strcpy(Member1.name, Member2.name);
printf("%s, %d\n", Member1.name, Member1.age);
if (NULL != Member1.name) {
free(Member1.name);
Member1.name = NULL;
}
if (NULL != Member2.name) {
free(Member2.name);
Member2.name = NULL;
}
system("pause");
return 0;
}
運行如下:
結論
使用C語言來說,深拷貝淺拷貝的概念我們不需要深究,在進行結構體拷貝的時候,結構體成員是非指針的話,那么直接賦值是沒有任何問題的,建議使用這種方式,避免淺拷貝這類不易發現的錯誤產生。
如果成員有指針類型,我們就需要重寫拷貝函數,自己定義拷貝行為了,這一點我們需要尤為注意。
原文鏈接:https://blog.csdn.net/yx5666/article/details/127124331
相關推薦
- 2023-01-19 C++?new與malloc和delete及free動態內存管理及區別介紹_C 語言
- 2022-12-09 Flutter?Widgets?MediaQuery控件屏幕信息適配_IOS
- 2022-06-20 Python使用MapReduce編程模型統計銷量_python
- 2022-11-13 linux?shell腳本學習指南_linux shell
- 2022-08-05 RedisConfig 配置文件
- 2022-06-09 Redis超詳細講解高可用主從復制基礎與哨兵模式方案_Redis
- 2022-02-12 redis 快捷啟動 注冊服務,jar包注冊成服務,開機啟動
- 2022-04-08 iOS實現簡單計算器功能_IOS
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支