当前位置: 首页 > article >正文

深拷贝、浅拷贝、移动语义

C++ 中的拷贝方式

1. 深拷贝(Deep Copy)

定义

深拷贝会复制对象的全部内容,包括对象中动态分配的资源。新对象与原对象完全独立,任何对新对象的修改都不会影响原对象。

实现

通常通过显式的拷贝构造函数或拷贝赋值运算符,手动分配新内存并复制资源。

示例

#include <iostream>
#include <cstring>

class MyClass {
    char* data;

public:
    MyClass(const char* str) {
        data = new char[strlen(str) + 1];
        strcpy(data, str);
    }

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

    ~MyClass() {
        delete[] data;
    }

    void print() const {
        std::cout << data << "\n";
    }
};

int main() {
    MyClass obj1("Hello");
    MyClass obj2 = obj1;  // 调用深拷贝构造函数
    obj2.print();         // 输出: Hello
    return 0;
}

特点

1.深拷贝是安全的,原对象和新对象的资源完全独立。
2.对象中有动态资源时需要手动实现深拷贝。
3.较耗费性能(特别是资源较大时)。

2. 浅拷贝(Shallow Copy)

定义

浅拷贝只复制对象中的指针或引用,而不复制它们所指向的实际资源。新对象和原对象共享同一块资源。

问题

如果不小心释放了共享的资源,会导致其他对象指向无效的内存,产生 悬挂指针(Dangling Pointer)。

示例

#include <iostream>
#include <cstring>

class MyClass {
    char* data;

public:
    MyClass(const char* str) {
        data = new char[strlen(str) + 1];
        strcpy(data, str);
    }

    // 默认浅拷贝(未自定义拷贝构造函数时)
    MyClass(const MyClass& other) = default;

    ~MyClass() {
        delete[] data;
    }

    void print() const {
        std::cout << data << "\n";
    }
};

int main() {
    MyClass obj1("Hello");
    MyClass obj2 = obj1;  // 浅拷贝,指向同一资源
    obj1.print();         // 输出: Hello
    obj2.print();         // 输出: Hello

    return 0;
}

特点

1.浅拷贝速度快,因为它仅复制指针的地址。
2.容易产生悬挂指针或资源泄漏问题。

3. 移动语义(Move Semantics)

定义

移动语义会将资源从一个对象“转移”到另一个对象,而不会创建或复制新的资源。原对象的资源被“搬走”,进入“有效但未定义状态”。

实现

使用移动构造函数和移动赋值运算符。

示例

#include <iostream>
#include <utility> // for std::move

class MyClass {
    char* data;

public:
    MyClass(const char* str) {
        data = new char[strlen(str) + 1];
        strcpy(data, str);
    }

    // 移动构造函数
    MyClass(MyClass&& other) noexcept : data(other.data) {
        other.data = nullptr;  // 释放原对象的所有权
    }

    ~MyClass() {
        delete[] data;
    }

    void print() const {
        std::cout << (data ? data : "Empty") << "\n";
    }
};

int main() {
    MyClass obj1("Hello");
    MyClass obj2 = std::move(obj1);  // 调用移动构造函数
    obj2.print();                   // 输出: Hello
    obj1.print();                   // 输出: Empty
    return 0;
}

特点

1.移动语义速度快,不需要深拷贝。
2.常用于临时对象或需要高效转移资源的场景。
3.需要实现移动构造函数和移动赋值运算符。

4. 对比总结

拷贝方式深拷贝浅拷贝移动语义
实现复杂度较高,需要手动复制资源简单,默认行为需要手动实现移动构造和赋值
效率慢,涉及内存分配和复制快,只复制指针非常快,只转移资源所有权
资源独立性独立的资源副本共享资源资源被转移,独占
适用场景资源独立且需频繁复制快速拷贝,无需独立资源资源需要转移时,高效操作

5.总结

  • 深拷贝:适用于需要独立资源的场景,比如资源管理类(文件、内存等)。
  • 浅拷贝:简单但容易导致问题,仅适用于无需独立资源的情况。
  • 移动语义:是现代 C++ 的高效资源管理方式,适合转移资源的场景。

http://www.kler.cn/a/523481.html

相关文章:

  • 解锁豆瓣高清海报:深度爬虫与requests进阶之路
  • fscan全家桶更新:fscan免杀版,可过360、火绒、微步云沙箱,其他的自行测试
  • 【Rust自学】14.6. 安装二进制crate
  • 网站如何正式上线(运维详解)
  • Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat
  • PostgreSQL 约束
  • Leetcode — 罗马数字转整数
  • leetcode 1343. 大小为 K 且平均值大于等于阈值的子数组数目
  • 虚幻基础07:蓝图接口
  • 2025春招,Netty面试题汇总
  • Vue.js 深度解析:响应式、虚拟 DOM 与编译优化的艺术
  • 一文了解性能优化的方法
  • 自定义数据集,使用 PyTorch 框架实现逻辑回归并保存模型,然后保存模型后再加载模型进行预测
  • 重回C语言之老兵重装上阵(十四)C语言头文件详解
  • LeetCode热题100(八)—— 438.找到字符串中所有字母异位词
  • 危机13小时:追踪一场GitHub投毒事件
  • 实验二---二阶系统阶跃响应---自动控制原理实验课
  • wx043基于springboot+vue+uniapp的智慧物流小程序
  • Direct2D 极速教程(2) —— 画淳平
  • 求解旅行商问题的三种精确性建模方法,性能差距巨大
  • android主题设置为..DarkActionBar.Bridge时自定义DatePicker选中日期颜色
  • woocommerce独立站与wordpress独立站的最大区别是什么
  • 每日OJ_牛客_小红的子串_滑动窗口+前缀和_C++_Java
  • 实验二 数据库的附加/分离、导入/导出与备份/还原
  • XCTF Illusion wp
  • 【C++动态规划 状态压缩】2741. 特别的排列|2020