浅拷贝和深拷贝
1.浅拷贝
浅拷贝,多个指针指向同一段内存,出现一处指针修改数据,其它指针的数据也发生改变。
1.1 面向过程的浅拷贝(C方式)
如下代码:
//下面程序,从键盘获取4个字符串,然后输出到屏幕
int main()
{
char buf[100];
char* strArr[4];//长度为4的字符指针数组,分别指向4个字符串
for (int i = 0; i <4 ; i++)//从键盘获取4个字符串
{
cin >> buf;
strArr[i] = buf;
}
for (int i = 0; i < 4; i++)//把4个字符串输出到屏幕
cout << strArr[i] << " ";
return 0;
}
在键盘中输入4个单词:Apple Banana Orange Peach
但是输出的结果却是:Peach Peach Peach Peach
原因如下:
假设buf的地址为200。第一次从键盘读取Apple,并把200这个地址赋值给strArr[0]。
第二次从键盘读取Banana,并把200这个地址赋值给strArr[1],注意这个地方的问题,由于buf这段内存只有一个,第二次赋值会把第一次的Apple覆盖。
第三次从键盘读取Orange,并把200这个地址赋值给strArr[2],但这时Orange把前面的输入覆盖了。
第四次从键盘读取Pear,并把200这个地址赋值给strArr[3]。但这是Pear把前面的输入覆盖了。
最后输出时strArr[0]到strArr[3]都去地址200处取字符串,就全部都是"Pear"。
这是一个典型的浅拷贝,多个指针指向同一段内存造成的。
1.2 面向对象的浅拷贝(类)
下面是一个有问题的类(StringBad类的简化版),只是为了演示浅拷贝的问题
**class CStr
{
private:
char* str;//字符串指针
public:
CStr(const char* s)//构造函数,通过s构造一个CStr类对象
{
str = new char[strlen(s) + 1];//动态创建内存
strcpy(str,s);//把s的内容复制到str
}
void set(const char* s)//修改字符串的值
{
delete[]str;//释放原来的内存
str = new char[strlen(s) + 1];//动态创建内存
strcpy(str, s);//把s的内容复制到str
}
void show()const
{
cout << str << endl;
}
};
int main()
{
CStr s1{"趣字节,有趣的编程"};
s1.show();//输出s1的内容
CStr s2 = s1; //把s1赋值给s2
s2.show();//输出s2的内容
s2.set("好好学习,天天向上");//修改s2的值
s2.show();//输出s2的内容
s1.show();//再输出s1的内容
return 0;
}
第25行,创建一个对象s1,并初始化为"趣字节,有趣的编程";
第28行,创建另一个对象s2,并把s1赋值给s2;
第29行,输出s2的内容,这是是s1赋值的值,这是正确的;
第31行,修改s2的内容,将其改为"好好学习,天天向上";
第32行,输出s2的内容,是修改后的值"好好学习,天天向上",这是正确的;
第33行,输出s1的值,应该是"趣字节,有趣的编程",但实际输出的却是"好好学习,天天向上",这是错误的。
错误的原因也是浅拷贝造成的,具体原因如下图:
2.深拷贝
深拷贝,即为每个指针创建一个单独的内存,然后再复制数据。
2.1 面向过程的深拷贝
把前面的浅拷贝程序进行适当的修改,如下:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
//深拷贝
//下面程序,从键盘获取4个字符串,然后输出到屏幕
int main()
{
char buf[100];
char* strArr[4];//长度为4的字符指针数组,分别指向4个字符串
for (int i = 0; i < 4; i++)//从键盘获取4个字符串
{
cin >> buf;
//strArr[i] = buf;//这是浅拷贝
//下面的是深拷贝
strArr[i] = (char*)malloc(strlen(buf) + 1);//1.创建单独的内存
strcpy(strArr[i],buf);//2.复制数据
}
for (int i = 0; i < 4; i++)//把4个字符串输出到屏幕
cout << strArr[i] << " ";
//最后需要释放动态内存
for (int i = 0; i < 4; i++)
free(strArr[i]);
return 0;
}
从上面的程序能够正常的输出。
第12行,为每个字符串创建单独的内存,用于存放数据。
第13行,将数据从buf复制到新创建的内存。
第20,21行,释放每个字符串单独创建的内存,否则出现内存泄漏。
本篇完!