为什么开辟到堆区:因为堆区的内存由程序员创建和释放,在函数体外也可以调用,在使用堆区的时候需要考虑拷贝时防止指针空挂的现象
浅拷贝造成的问题
#include <iostream>
#include <string>
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); // 在堆区申请地址
}