问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

C++:深拷贝vs浅拷贝(通俗易懂)

创作时间:
作者:
@小白创作中心

C++:深拷贝vs浅拷贝(通俗易懂)

引用
CSDN
1.
https://m.blog.csdn.net/Ethan_Rich/article/details/145452151

在 C++(尤其是 OpenCV、STL 容器等)中,拷贝数据时主要有深拷贝(Deep Copy)浅拷贝(Shallow Copy)两种方式。它们的区别在于是否复制数据本身还是仅复制指针

1. 什么是浅拷贝(Shallow Copy)?

浅拷贝只是复制指针,不会创建新的数据副本。两个对象共享相同的数据地址,修改一个对象的数据会影响另一个对象。

示例 1:OpenCV cv::Mat 的浅拷贝

cv::Mat img1 = cv::imread("image.jpg");
cv::Mat img2 = img1;  // 浅拷贝
  • img2 并没有创建新的数据副本,只是复制了 img1 的元数据(如 data 指针)。
  • img1img2 共享相同的图像数据,修改 img2 也会影响 img1

验证:

img2.setTo(cv::Scalar(0, 255, 0));  // 把所有像素变成绿色
cv::imshow("Original Image", img1); // 发现 img1 也变成了绿色!
cv::waitKey(0);

示例 2:C++ 指针的浅拷贝

int* a = new int(10);
int* b = a;  // 浅拷贝:b 只是复制了 a 的指针
*b = 20;  // 修改 b 也会影响 a
std::cout << *a << std::endl;  // 输出 20
  • b = a; 只是让 b 指向 a 的数据,而没有创建新数据
  • 改变 b 指向的数据,a 也会受到影响。

2. 什么是深拷贝(Deep Copy)?

深拷贝创建数据的完整副本,对象之间不共享数据,修改一个对象不会影响另一个对象。

示例 1:OpenCV cv::Mat 的深拷贝

cv::Mat img1 = cv::imread("image.jpg");
cv::Mat img2 = img1.clone();  // 深拷贝
  • clone() 创建了 img1 的完整副本,img2 拥有独立的数据内存。
  • img1img2完全独立的,修改 img2 不会影响 img1

验证:

img2.setTo(cv::Scalar(0, 255, 0));  // 把 img2 变成绿色
cv::imshow("Original Image", img1); // img1 仍然是原图
cv::imshow("Copied Image", img2);   // img2 是绿色的
cv::waitKey(0);

示例 2:C++ 指针的深拷贝

int* a = new int(10);
int* b = new int(*a);  // 深拷贝:创建新的 int 并复制值
*b = 20;  // 只改变 b,不影响 a
std::cout << *a << std::endl;  // 输出 10
std::cout << *b << std::endl;  // 输出 20
  • new int(*a); 创建了新的内存,并复制 a 的值。
  • ab 现在是两个独立的变量,互不影响。

3. 深拷贝 vs. 浅拷贝的比较

4. 何时使用浅拷贝 vs. 深拷贝

5. 如何在 C++ 代码中实现深拷贝

如果你自己写 C++ 类,需要手动实现深拷贝,避免默认的浅拷贝。

class MyClass {
private:
    int* data;
public:
    // 构造函数
    MyClass(int value) {
        data = new int(value);
    }
    // 深拷贝构造函数
    MyClass(const MyClass& other) {
        data = new int(*other.data);  // 深拷贝
    }
    // 赋值运算符
    MyClass& operator=(const MyClass& other) {
        if (this == &other) return *this;  // 避免自赋值
        delete data;  // 释放旧内存
        data = new int(*other.data);  // 重新分配
        return *this;
    }
    // 析构函数
    ~MyClass() {
        delete data;
    }
    void print() { std::cout << *data << std::endl; }
};
int main() {
    MyClass obj1(10);
    MyClass obj2 = obj1;  // 深拷贝
    obj2.print();  // 输出 10
    return 0;
}

6. OpenCV 中深拷贝与浅拷贝

浅拷贝

cv::Mat A = cv::imread("image.jpg");
cv::Mat B = A;  // B 只是 A 的引用

深拷贝

cv::Mat A = cv::imread("image.jpg");
cv::Mat B = A.clone();  // B 拷贝 A 的数据

7. 总结

  • 浅拷贝只复制指针,不复制数据,多个对象共享相同的数据。
  • 深拷贝创建数据的完整副本,两个对象独立存储数据,互不影响。
  • 浅拷贝更快,但容易导致数据共享问题深拷贝更安全,但消耗更多内存
  • OpenCV, Mat.clone()copyTo() 执行深拷贝,而 = 只是浅拷贝
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号