首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >面试官问:解释一下深拷贝和浅拷贝的区别,并说明结构体场景的具体对比

面试官问:解释一下深拷贝和浅拷贝的区别,并说明结构体场景的具体对比

作者头像
C语言中文社区
发布2026-01-27 11:24:00
发布2026-01-27 11:24:00
3290
举报
文章被收录于专栏:C语言中文社区C语言中文社区

一、核心概念理解

  • 浅拷贝(Shallow Copy):只拷贝"表面"数据,对于指针成员,只拷贝指针的值(即内存地址),而不拷贝指针指向的实际内容。相当于给同一个房间多配了一把钥匙,两把钥匙都能打开同一个房间。
  • 深拷贝(Deep Copy):不仅拷贝结构体的所有成员,对于指针成员,会先为其分配新的内存空间,再将原指针指向的内容完整复制到新空间中。相当于重新盖了一间一模一样的房间,新钥匙开新房间,旧钥匙开旧房间,互不影响。

二、结构体场景的具体对比

通过一个包含指针的结构体示例,直观展示两者的区别:

1. 定义基础结构体
代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 定义包含指针的结构体
typedef struct {
    int id;
    char *name;  // 指针成员,指向堆内存
} Student;
2. 浅拷贝示例(直接赋值/简单拷贝)
代码语言:javascript
复制
// 浅拷贝:直接赋值结构体,仅拷贝指针地址
void shallow_copy_demo() {
    // 初始化第一个结构体
    Student s1;
    s1.id = 101;
    s1.name = (char *)malloc(20 * sizeof(char));
    strcpy(s1.name, "Zhang San");

    // 浅拷贝:直接赋值,仅拷贝指针地址
    Student s2 = s1;

    printf("浅拷贝后:\n");
    printf("s1.name: %s, 地址: %p\n", s1.name, s1.name);
    printf("s2.name: %s, 地址: %p\n", s2.name, s2.name);

    // 修改s2的name,s1的name也会被修改(指向同一块内存)
    strcpy(s2.name, "Li Si");
    printf("修改s2.name后:\n");
    printf("s1.name: %s\n", s1.name);  // 输出 Li Si
    printf("s2.name: %s\n", s2.name);  // 输出 Li Si

    // 释放内存:两次释放同一块内存,导致内存崩溃
    free(s1.name);
    // free(s2.name);  // 执行此句会触发内存错误(double free)
}
3. 深拷贝示例(手动分配内存+拷贝内容)
代码语言:javascript
复制
// 深拷贝函数:为指针成员分配新内存,并拷贝内容
void deep_copy(Student *dest, const Student *src) {
    // 拷贝非指针成员
    dest->id = src->id;
    // 为指针成员分配新内存
    dest->name = (char *)malloc(strlen(src->name) + 1);
    if (dest->name == NULL) {  // 内存分配失败处理
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }
    // 拷贝指针指向的内容
    strcpy(dest->name, src->name);
}

void deep_copy_demo() {
    // 初始化第一个结构体
    Student s1;
    s1.id = 101;
    s1.name = (char *)malloc(20 * sizeof(char));
    strcpy(s1.name, "Zhang San");

    // 深拷贝
    Student s2;
    deep_copy(&s2, &s1);

    printf("深拷贝后:\n");
    printf("s1.name: %s, 地址: %p\n", s1.name, s1.name);
    printf("s2.name: %s, 地址: %p\n", s2.name, s2.name);  // 地址与s1不同

    // 修改s2的name,s1的name不受影响
    strcpy(s2.name, "Li Si");
    printf("修改s2.name后:\n");
    printf("s1.name: %s\n", s1.name);  // 输出 Zhang San
    printf("s2.name: %s\n", s2.name);  // 输出 Li Si

    // 分别释放各自的内存,无冲突
    free(s1.name);
    free(s2.name);
}
4. 主函数测试
代码语言:javascript
复制
int main() {
    printf("=== 浅拷贝示例 ===\n");
    shallow_copy_demo();

    printf("\n=== 深拷贝示例 ===\n");
    deep_copy_demo();

    return 0;
}

三、关键区别总结(结构体场景)

特性

浅拷贝

深拷贝

指针成员处理

仅拷贝指针地址(指向同一块内存)

分配新内存,拷贝指针指向的内容

内存独立性

拷贝后结构体共享同一块堆内存

拷贝后结构体拥有独立的堆内存

修改影响

修改一个结构体的指针内容,另一个也变

修改一个不影响另一个

内存释放

易出现重复释放(double free)

各自释放独立内存,无冲突

实现方式

直接赋值结构体即可

手动编写拷贝函数,分配内存+拷贝内容

总结

  1. 浅拷贝的核心问题:处理含指针的结构体时,仅拷贝指针地址,导致多个结构体共享同一块堆内存,修改会相互影响,释放时易触发内存错误(double free 或内存泄漏)。
  2. 深拷贝的核心解决思路:为指针成员重新分配内存,再拷贝指针指向的实际内容,保证每个结构体拥有独立的内存空间,修改和释放互不干扰。
  3. 在C语言中,结构体默认的赋值操作(如Student s2 = s1)是浅拷贝,若结构体包含指针成员,必须手动实现深拷贝函数才能避免内存问题。
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 C语言中文社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、核心概念理解
  • 二、结构体场景的具体对比
    • 1. 定义基础结构体
    • 2. 浅拷贝示例(直接赋值/简单拷贝)
    • 3. 深拷贝示例(手动分配内存+拷贝内容)
    • 4. 主函数测试
  • 三、关键区别总结(结构体场景)
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档