浅拷贝造成的问题为什么开辟到堆区:因为堆区的内存由程序员创建和释放,在函数体外也可以调用,在使用堆区的时候需要考虑拷贝时防止指针空挂的现象
#include#include using namespace std; class Student { public: string m_name; int* p_age; // 存放年龄的指针 Student() { cout << "默认构造函数调用" << endl; } Student(string name,int age) { m_name=name; p_age=new int(age); // 将age存到堆区 cout << "有参构造函数调用" << endl; } ~Student() { if(p_age!=NULL) // 堆区由程序员调用也需要由程序员释放 { delete(p_age); // 释放分配的空间 p_age=NULL; // 将内存指针置空 } cout << "析构函数调用" << endl; } }; int main(void) { Student s1("Mike",18); cout << "NAME:" << s1.m_name << " AGE:" << *s1.p_age << " address:" << s1.p_age << endl; Student s2(s1); cout << "NAME:" << s2.m_name << " AGE:" << *s2.p_age << " address:" << s2.p_age << endl; return 0; }
这个时候出发了错误,是因为在系统建立的默认拷贝函数,将s1对象中的m_age的值完整的复制给了s2对象中的m_age的值,执行析构函数时,根据栈的规则,先进后出,释放了掉s2.m_age的值;
为什么判断s1.m_age是否为空,还会产生错误?这是因为浅复制的作用,s1.m_age的字面是不为空,但是实际指向的地址已经在s2.m_age中被释放掉了,所以产生了错误
NAME:Mike AGE:18 address:0x7d1540 // s1.m_age == s2.m_age NAME:Mike AGE:18 address:0x7d1540
浅拷贝其实就是因为缺少拷贝构造函数,使用系统的默认拷贝构造函数所引发的问题
// 系统使用的默认拷贝构造函数
Student(const Student & s)
{
m_name=s.m_name;
p_age=s.p_age; // 仅复制值而为独立分开内存空间
}
// 自定义默认拷贝构造函数
Student(const Student & s)
{
cout << "拷贝构造函数" << endl;
m_name=s.m_name;
p_age=new int(*s.p_age); // 在堆区申请地址
}



