深浅拷贝解析

深浅拷贝解析
浅拷贝只拷贝指针,但拷贝后两个指针指向同一个内存空间;深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针指向两个不同地址。当类成员不包括指针何引用时,浅拷贝并无问题;但对于指针与引用成员,当对象的生命周期结束后,浅拷贝会造成同一块内存单元被释放两次,导致内存泄漏。

       调用拷贝构造函数后,浅拷贝依然还有联系,深拷贝的两个对象完全独立。浅拷贝类似于文件创建快捷方式,而深拷贝好比文件复制。编译器默认提供的默认拷贝构造函数是浅拷贝,深拷贝的构造函数需自己实现。

1)普通成员

(1)浅拷贝

eg:

#include <iostream>

using std::cout;
using std::endl;

class CExample 
{
private:
	int a;

public:
	CExample(int b) 
	{
		a = b;
		cout << "默认构造函数" << endl;
	}

	~CExample()
	{
		cout << "析构函数" << endl;
	}
};

int main(int argc, char* argv[]) 
{
	CExample A(100);
	CExample B(A);
	return 0;
}

在Windows下的VS2015下编译并运行,运行结果:

默认构造函数

析构函数

析构函数

 

在Ubuntu下的g++下编译并运行,运行结果:

默认构造函数

析构函数

析构函数


(2)深拷贝

eg:

#include <iostream>

using std::cout;
using std::endl;

class CExample
{
private:
	int a;

public:
	CExample(int b)
	{
		a = b;
		cout << "默认构造函数" << endl;
	}

	CExample(const CExample& C)
	{
		a = C.a;
		cout << "复制构造函数" << endl;
	}


	~CExample()
	{
		cout << "析构函数" << endl;
	}
};

int main(int argc, char* argv[])
{
	CExample A(100);
	CExample B(A);
	return 0;
}

在Windows下的VS2015下编译并运行,运行结果:

默认构造函数

复制构造函数

析构函数

析构函数

 

在Ubuntu下的g++下编译并运行,运行结果:

默认构造函数

复制构造函数

析构函数

析构函数


2)含有指针成员

(1)浅拷贝

eg:

#include <iostream>

using std::cout;
using std::endl;

class A
{
public:
	A()
	{
		m_data = new char(100);
		cout << "默认构造函数" << endl;
	}

	~A()
	{
		if (m_data != NULL)
		{
			delete m_data;
			m_data = NULL;
			cout << "析构函数" << endl;
		}
	}

private:
	char *m_data;
};

int main(int argc, char* argv[])
{
	A a;
	A b(a);
	return 0;
}
在Windows下的VS2015下编译并运行,并未检测到内存泄漏,运行结果:
默认构造函数
析构函数


在Ubuntu下的g++下编译并运行,运行结果:

默认构造函数

析构函数

*** glibc detected *** ./test.exe: double free or corruption (fasttop): 0x0000000001c24010 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7da26)[0x7fc7041b2a26]
./test.exe[0x400a63]
./test.exe[0x400985]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7fc7041567ed]
./test.exe[0x400889]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:01 942530                             /home/austin/Workspace/test.exe
00600000-00601000 r--p 00000000 08:01 942530                             /home/austin/Workspace/test.exe
00601000-00602000 rw-p 00001000 08:01 942530                             /home/austin/Workspace/test.exe
01c24000-01c45000 rw-p 00000000 00:00 0                                  [heap]
7fc703e39000-7fc703f34000 r-xp 00000000 08:01 271154                     /lib/x86_64-linux-gnu/libm-2.15.so
7fc703f34000-7fc704133000 ---p 000fb000 08:01 271154                     /lib/x86_64-linux-gnu/libm-2.15.so
7fc704133000-7fc704134000 r--p 000fa000 08:01 271154                     /lib/x86_64-linux-gnu/libm-2.15.so
7fc704134000-7fc704135000 rw-p 000fb000 08:01 271154                     /lib/x86_64-linux-gnu/libm-2.15.so
7fc704135000-7fc7042e9000 r-xp 00000000 08:01 271145                     /lib/x86_64-linux-gnu/libc-2.15.so
7fc7042e9000-7fc7044e8000 ---p 001b4000 08:01 271145                     /lib/x86_64-linux-gnu/libc-2.15.so
7fc7044e8000-7fc7044ec000 r--p 001b3000 08:01 271145                     /lib/x86_64-linux-gnu/libc-2.15.so
7fc7044ec000-7fc7044ee000 rw-p 001b7000 08:01 271145                     /lib/x86_64-linux-gnu/libc-2.15.so
7fc7044ee000-7fc7044f3000 rw-p 00000000 00:00 0 
7fc7044f3000-7fc704508000 r-xp 00000000 08:01 266213                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc704508000-7fc704707000 ---p 00015000 08:01 266213                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc704707000-7fc704708000 r--p 00014000 08:01 266213                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc704708000-7fc704709000 rw-p 00015000 08:01 266213                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7fc704709000-7fc7047eb000 r-xp 00000000 08:01 3678310                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7fc7047eb000-7fc7049ea000 ---p 000e2000 08:01 3678310                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7fc7049ea000-7fc7049f2000 r--p 000e1000 08:01 3678310                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7fc7049f2000-7fc7049f4000 rw-p 000e9000 08:01 3678310                    /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16
7fc7049f4000-7fc704a09000 rw-p 00000000 00:00 0 
7fc704a09000-7fc704a2b000 r-xp 00000000 08:01 271151                     /lib/x86_64-linux-gnu/ld-2.15.so
7fc704c0d000-7fc704c12000 rw-p 00000000 00:00 0 
7fc704c27000-7fc704c2b000 rw-p 00000000 00:00 0 
7fc704c2b000-7fc704c2c000 r--p 00022000 08:01 271151                     /lib/x86_64-linux-gnu/ld-2.15.so
7fc704c2c000-7fc704c2e000 rw-p 00023000 08:01 271151                     /lib/x86_64-linux-gnu/ld-2.15.so
7fff8a9ec000-7fff8aa0d000 rw-p 00000000 00:00 0                          [stack]
7fff8ab7d000-7fff8ab7f000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Aborted (core dumped)


(2)深拷贝

eg:

#include <iostream>
#include <cstring>

using std::cout;
using std::endl;

class A
{
public:

	A()
	{
		m_pdata = new char(100);
		cout << "默认构造函数" << endl;
	}

	A(const A& r)
	{
		m_pdata = new char(100);    
		memcpy(m_pdata, r.m_pdata, strlen(r.m_pdata));
		cout << "copy构造函数" << endl;
	}

	~A()     
	{
		if (m_pdata != NULL)
		{
			delete m_pdata;
			cout << "析构函数" << endl;
		}
	}

private:
	char *m_pdata;    
};

int main(int argc, char* argv[])
{
	A a;
	A b(a);   
	return 0;
}
在Windows下的VS2015下编译并运行,运行结果:
默认构造函数
copy构造函数
析构函数
析构函数


在Ubuntu下的g++下编译并运行,运行结果:
默认构造函数
copy构造函数
析构函数
析构函数

参考文献

[1]C++的深拷贝与浅拷贝.  http://blog.csdn.net/lpp0900320123/article/details/39007047.

[2]对深拷贝与浅拷贝的再次理解. http://blog.csdn.net/feitianxuxue/article/details/9275979.

[3]如何理解 C++ 中的深拷贝和浅拷贝?. https://www.zhihu.com/question/36370072?sort=created.

[4] C++深拷贝与浅拷贝. http://blog.chinaunix.net/uid-24645949-id-2110772.html.

[5] C++浅拷贝和深拷贝的区别. http://blog.sina.com.cn/s/blog_914476ec01018jcw.html.

[6] C++深浅拷贝浅析. http://www.jizhuomi.com/software/291.html.

[7]Deep copy vs Shallow copy. http://stackoverflow.com/questions/2657810/deep-copy-vs-shallow-copy.

[8] C++ Notes: OOP: Copy Constructors. http://www.fredosaurus.com/notes-cpp/oop-condestructors/copyconstructors.html.

[9] 深拷贝和浅拷贝的区别. http://blog.chinaunix.net/uid-24981687-id-3038952.html.

[10] Object copying. https://en.wikipedia.org/wiki/Object_copy.

[11]C++回顾之深浅拷贝、禁止拷贝、空类的默认成员. http://blog.csdn.net/ab198604/article/details/19125419.

[12]C++程序设计原理与实践:373.

 

注:为了便于自己学习,无心侵权,尽可能将所引用的文章列举出来;有些文章的内容可能会与原作重复度较高,还请谅解。如作者举报,愿意删除此文。




  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值