C++ delete和置為NULL
先上一段代碼:
class Object
{
public:
explicit Object(int num) : m_num(num){}
void function1()
{
std::cout << "function1()" << std::endl;
}
void function2()
{
std::cout << "function2(): " << m_num << std::endl;
}
private:
int m_num;
};
簡單的定義了一個名為Object的類,然后測試一下
int main()
{
Object *obj = new Object(10);
delete obj;
obj->function1();
return 0;
}
編譯運行一下:obj->function1()居然可以正常運行。已經執行delete掉了,為什么還能運行呢?再測試一下obj->function2()看看
int main()
{
Object *obj = new Object(10);
delete obj;
obj->function2();
return 0;
}
編譯運行一下:發現obj->function2()也可以運行,但是運行的信息貌似不對,打印出來的m_num值不對哇。
再測試一下:
int main()
{
Object *obj = new Object(10);
delete obj;
obj = nullptr;
obj->function1();
obj->function2();
return 0;
}
編譯運行一下:發現obj->function1()可以運行,obj->function2()運行出現異常。這3個簡單的測試說明了一個什么問題呢?
其實很簡單,首先obj->function1()沒有使用到類的實例的內存,實例被釋放對它來說是無所謂的,壓根不會影響它的運行。
再看obj->function2()這個函數,它使用到了類實例中的m_num, 也就是說它使用了類實例的內存,delete只是將類實例的內存所有權歸還給了系統,並不是清空了這塊內存,內存是客觀存在的,它是可以訪問的。因此obj->function2()還是可以運行的,但是類實例已經放棄了這塊內存的所有權,obj->function2()再去讀這塊內存會讀到什么是不確定的。執行obj = nullptr后,再運行obj->function2()沒有內存去訪問,因此會報錯。
不管如何,delete一個類的實例后,都不應該再去訪問類的成員函數,不論它是否能正常運行正常,它都危險的。
delete一個類的實例后,置位NULL,可以在一定程度上避免危險的發生。
同時需要注意的一點是new和delete相當於借和還,並不是簡單的創建和銷毀。