调用拷贝构造函数后,浅拷贝依然还有联系,深拷贝的两个对象完全独立。浅拷贝类似于文件创建快捷方式,而深拷贝好比文件复制。编译器默认提供的默认拷贝构造函数是浅拷贝,深拷贝的构造函数需自己实现。
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++下编译并运行,运行结果:
默认构造函数
析构函数
析构函数
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.
注:为了便于自己学习,无心侵权,尽可能将所引用的文章列举出来;有些文章的内容可能会与原作重复度较高,还请谅解。如作者举报,愿意删除此文。