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
指针)。img1
和img2
共享相同的图像数据,修改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
拥有独立的数据内存。img1
和img2
是完全独立的,修改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
的值。a
和b
现在是两个独立的变量,互不影响。
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()
执行深拷贝,而=
只是浅拷贝。
热门推荐
春天去婺源·篁嶺拍大片,你准备好了吗?
高通VS联发科:谁才是双卡双待之王?
尿酸高吃什么药降尿酸效果好?常见降尿酸药物推荐!
打破认知:尿酸并非百害无一利,它在人体内可以这样正常工作
知画猫&Gatan教你掌握光影技巧
黄河壶口瀑布:临汾必打卡自然奇观
“万里山河路”带你玩转临汾古建
南通博物苑:中国博物馆事业的发端
南通植物园荷花展:万维莎睡莲惊艳亮相,30余种荷花争奇斗艳
南通狼山:古迹探秘与文化寻踪
南通一日游:打卡网红景点濠河和狼山
高老庄的猪八戒:从妖怪到女婿的逆袭之路
纸箱DIY盾牌:贾晴山教你玩转亲子手工
百余项科目练就“超能力” 中国航天员训练揭秘
古人“纳妾”真相:纳妾条件高,多数妾室都是由正妻主动迎上门
古代社会结构中的男性身份象征:妻、妾、妓的角色与地位
为什么安装了自闭阀,还要安装切断阀和报警器?
楼宇燃气调压站安装调试指南
什么是巨鹿之战?这场战役发生在何时何地?对历史的影响是什么?
建筑工地消防安全指南:隐患识别与防范措施
燃气阀门保养攻略:维护与更换全解析
燃气阀安装全攻略:位置、步骤与注意事项
泰山赤灵芝1号:种植技巧大揭秘!
灵芝:养生界的“仙草”,这样吃最养生!
灵芝三萜:抗肿瘤研究的新突破
中国代表团亚冬会百金里程碑:冰雪运动的新纪元
8金8银5铜!中国队领跑哈尔滨亚冬会,高亭宇、林孝埈、李方慧闪耀赛场
白青蛙养殖:如何避免踩坑?
里耶秦简揭秘:中国古代乘法口诀的奥秘
九九乘法表:古人的数学魔法