浅拷贝,多个指针指向同一段内存,出现一处指针修改数据,其它指针的数据也发生改变。
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"。
这是一个典型的浅拷贝,多个指针指向同一段内存造成的。
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;
}
MICROSOFT VISUAL STUDIO 调趣字节,有趣的编程S1最初的值趣字节,有趣的编程S2最初的值好好学习,天天向上S2修改后的值好好学习,天天向上S1没有修改,但值不对了
第25行,创建一个对象s1,并初始化为"趣字节,有趣的编程";
第28行,创建另一个对象s2,并把s1赋值给s2;
第29行,输出s2的内容,这是是s1赋值的值,这是正确的;
第31行,修改s2的内容,将其改为"好好学习,天天向上";
第32行,输出s2的内容,是修改后的值"好好学习,天天向上",这是正确的;
第33行,输出s1的值,应该是"趣字节,有趣的编程",但实际输出的却是"好好学习,天天向上",这是错误的。
错误的原因也是浅拷贝造成的,具体原因如下图: