标签:并且 重复 c++类 main 编译器 size iss ast cout
深度拷贝和浅拷贝在c语言中就经常遇到的了,在这里我简单描述。
一般的赋值操作是深度拷贝:
//深度拷贝
int a = 5;
int b = a;
所谓深度拷贝,即为在堆栈内存中新开辟了一块区域,存储着拷贝过来的数据。以上述代码为例,a和b分别指向内存中不同的地址,而两部分地址中存储着相同的5。
简单的指针指向,则是浅拷贝:
//浅拷贝
int a = 8;
int *p;
p = &a;
//另一种浅拷贝
char* str1 = "HelloWorld";
char* str2 = str1;
浅拷贝的特点是,拷贝前后的两个变量指向的是同一个地址。总而言之,拷贝者和被拷贝者若是同一个地址,则为浅拷贝,反之为深拷贝。
将上面的浅拷贝改为深度拷贝后:
//深度拷贝
int a = 8;
int *p = new int;
*p = a;
char* str1 = "HelloWorld";
int len = strlen(str1);
char *str2 = new char[len];
memcpy(str2, str1, len);
以字符串拷贝为例,浅拷贝后,str1和str2同指向0x123456,不管哪一个指针,对该空间内容的修改都会影响另一个指针。
深拷贝后,str1和str2指向不同的内存空间,各自的空间的内容一样。因为空间不同,所以不管哪一个指针,对该空间内容的修改都不会影响另一个指针。
类的默认拷贝构造函数采用的是浅拷贝,也就是说拷贝者和被拷贝者的指向的内存空间是一致的。
在以下情况中:
1、通过使用另一个同类型的对象来初始化新创建的对象,即用已有对象给新创建对象赋值。
2、对象作为函数参数并且发生值传递时。
3、对象作为函数返回值并且发生值传递时。
拷贝构造函数会被调用,现在我们分别看一下如果类中含有动态分配空间的话以上三种情况下会发生什么。
Line line2 = line1;//调用默认拷贝构造函数
由于发生了浅拷贝,现在line2和line1指向的是同一块内存空间,由于类中含有动态分配的空间,当main函数结束时,这些空间被释放,就出现了line1与line2释放同一处空间的情况,编译器会报错:
即发生了对同一块内存空间的重复释放,而这一般是不被允许的。
由参数传递的知识,我们可以知道,发生值传递时,是用实参通过拷贝构造函数来对形参赋值,形参与实参在默认拷贝下会指向同一段内存空间。
void display(Line obj)
{
cout << "line 大小 : " << obj.getLength() <<endl;
}
······
Line line(10);
display(line);
上例中,形参obj与实参line中动态分配部分指向同一段内存,当函数调用结束时,形参obj被消灭,与此同时,本来由line指向的内存空间被释放,line变成了指向一段自由空间,这也是不被允许的。
这里也是发生了值传递,道理和2、是一样的,不再赘述。
为避免上述问题,当类中含有动态分配空间时,自定义一个深度拷贝的拷贝构造函数和赋值运算符是必要的。具体构造方法请看本人博客里另两篇文章《c++拷贝(复制)构造函数》和《c++类赋值运算符重载》
标签:并且 重复 c++类 main 编译器 size iss ast cout
原文地址:https://www.cnblogs.com/kenkong20/p/14306192.html