#include<iostream>
using namespace std;
class CGirl
{
public:
int m_age;
int m_weight;
int* m_ptr;
CGirl(int age=18, int weight=150) // 构造函数
{
m_age=age;
m_weight=weight;//初始化成员变量
m_ptr=nullptr; //注意点1!!!!!!!!!!!!!!!!!!!!
//m_ptr=new int(15) //实际上应该写成这样,在堆(heap)中创建其他的内存空间放置变量
cout<<"调用了构造函数"<<endl;
}
CGirl(const CGirl &other){
m_age=other.m_age;
m_weight=other.m_weight;
m_ptr=other.m_ptr; // 浅拷贝
cout<<"调用了拷贝构造函数"<<endl;
}
~CGirl() // 析构函数
{
delete m_ptr;
m_ptr=nullptr;
cout<<"调用了析构函数"<<endl;
}
void showgirl()
{
cout<<"年龄:"<<m_age<<endl;
cout<<"体重:"<<m_weight<<endl;
cout<<"指针:"<<m_ptr<<endl;
cout<<"指针指向的值:"<<*m_ptr<<endl; // 注意点2!!!!!!!对空指针解引用是违法的,就是常说的野指针
}
};
int main(){
CGirl dengziqi;
dengziqi.showgirl();
CGirl liyuchun(dengziqi);
liyuchun.showgirl();
return 0;
}
在这里的main函数中,先创建了一个CGirl的对象dengziqi,然后调用其成员函数showgirl()输出其信息,然后把对象dengziqi作为传入参数传入CGirl的拷贝构造函数来重新创建一个新的变量liyuchun,然后调用showgil()输出liyuchun的信息,(当然这里我没有修改,liyuchun和dengziqi的信息是一样的),之后对象dengziqi会先调用析构函数~CGirl去删除指针m_ptr,由于liyuchun在调用拷贝构造函数的时候创建的m_ptr指针是浅拷贝,这意味着 dengziqi._ptr和 dengziqi.m_ptr
都指向相同的地址当liyuchun再次调用析构函数去删除m_ptr的时候,这个时候就会出错,因为在dengziqi调用析构函数的时候已经把m_ptr所指向的内存已经释放掉了,此时m_ptr就是一个悬停针,对悬停指针delete是未定义行为会导致程序崩溃报错。
悬垂指针:悬垂指针是指向已经释放或失效内存的指针。例如,当一个指针被用来释放一块内存后,没有被设置为 nullptr
,它仍然指向那个现在无效的内存地址。这种指针是危险的,因为它指向的内存可能已经被重新分配和使用,所以对这个指针的任何操作都可能导致不可预测的行为或程序崩溃。悬垂指针是野指针的一种。
野指针:野指针是指尚未初始化或已经释放的指针。这样的指针可能指向任意的内存地址,包括有效或无效的内存区域。野指针通常是由于指针声明而没有适当初始化或指针在释放后没有设置为 nullptr
而产生的。野指针的危险在于它可能指向任何地方,其使用可能导致程序错误、数据损坏或安全漏洞。