2012-12-05 36 views
2

如果指針設置爲NULL,則不會引用它或通過它也是NULL。這裏是一個編譯例如,當您嘗試運行它,將炸彈:如果指針設置爲NULL,則不會引用它或通過它也爲NULL

#include <string> 
#include <iostream> 

#define NULL 0 

class Seedcoat { 
public: 
    //Seedcoat(); 
    std::string Name; 
    int Weight; 
}; 

class Seed { 
public: 
    //Seed(); 
    std::string Name; 
    int Weight; 
    Seedcoat* ItsSeedcoat; 
}; 

class Apple { 
public: 
    //Apple(); 
    std::string Name; 
    int Weight; 
    Seed* ItsSeed; 
}; 

int main() 
{ 
///////Apple Objects Begin/////// 
    Apple  MyApple; 
    Seed  MySeed; 
    Seedcoat MySeedCoat; 

    MyApple.ItsSeed = &MySeed; 
    MyApple.ItsSeed->ItsSeedcoat = &MySeedCoat; 
    MyApple.ItsSeed->ItsSeedcoat->Weight = 2; 

    if (MyApple.ItsSeed != NULL) { 
     std::cout << "The weight of the apple seed's seedcoat is " << MyApple.ItsSeed->ItsSeedcoat->Weight <<".\n"; 
    } 

    MyApple.ItsSeed = NULL; 

    if (MyApple.ItsSeed->ItsSeedcoat != NULL) { 
     std::cout << "The weight of the apple seed's seedcoat is " << MyApple.ItsSeed->ItsSeedcoat->Weight <<".\n"; 
    } 

    return 0; 
} 

所以我的問題是:爲什麼這

MyApple.ItsSeed->ItsSeedcoat != NULL 

返回true。我認爲這不會因爲ItsSeed被設置爲NULL - 但它仍然會嘗試引用ItsSeedcoat的權重值 - 然後它會因爲ItsSeed不存在而被推測爲炸彈。我意識到有很多簡單的方法可以解決這個問題 - 這個例子只是爲了展示我正在觀察的行爲。這是否值得關注? - 或者這是正常的行爲?這樣做的原因是什麼?謝謝。

+0

除了給出的答案,你應該知道你沒有將對象設置爲NULL。您只能將指針設置爲NULL。指針不是對象。指針只指向對象。當您爲該指針賦值時,它以前指向的對象完全不受影響。 –

+0

這是真的。我做了一個修改以澄清。 – Stepan1010

+0

'ItsSeed'當然存在。它是一個指針,它的值是NULL。這意味着'MyApple.ItsSeed == NULL'。所以你實際做的是:'NULL-> ItsSeedcoat!= NULL'。顯然這是一個NULL指針解引用。空指針取消引用的通常結果是程序將崩潰。 –

回答

3

C++不會握住你的手。將指針設置爲空僅將該指針設置爲空。它不會像Java或Python中預期的那樣清除任何子對象或釋放任何內存。

一旦將指針設置爲空,訪問MyApple.ItsSeed->ItsSeedcoat就不再合法,因此可能發生任何事情。

在你的特定問題中,我認爲構圖可能是一個更好的解決方案。但是,如果您確實需要在C++中管理內存分配/釋放,我強烈建議使用一個適當的智能指針,它可以爲您提供與其他語言的垃圾收集器大致相等的功能。

我也建議你不要自己定義NULL,因爲一些頭文件已經爲C定義了它。在C++ 03中,我通常建議在C++ 11中使用文字0,你可以使用nullptr關鍵字。

+0

+1實際回答問題 – Joe

+0

就我目前的理解而言,它要求我寫更多的if語句,以確保在我嘗試訪問之前確保通過不存在的(空)父指針引用的所有內容實際存在用它做任何事情。 – Stepan1010

+1

@ Stepan1010在C++中,你通常設計你的代碼首先不需要*這些檢查。你給你的班級一套不變的,然後你總是知道什麼是安全的訪問。有時你需要'if'檢查(例如在鏈表中)。 –

1

MyApple.ItsSeed設置爲NULL後,不允許取消引用MyApple.ItsSeed的取消引用,這意味着不允許使用表達式MyApple.ItsSeed->ItsSeedcoat

這不一定會拋出異常,但其行爲是未定義的。

1

這是未定義的行爲,任何事情都可能發生。

格外,

MyApple.ItsSeed = NULL; 
if (MyApple.ItsSeed->ItsSeedcoat != NULL) 

你不允許取消引用NULL指針。就這麼簡單。如果你這樣做,任何行爲都是合規的。

0

解引用NULL指針會導致未定義的行爲。爲了獲得成員ItsSeedCoat,您必須取消引用ItsSeed,您已將其設置爲NULL。

0

在您的示例中,將MyApple.ItsSeed設置爲Seed *爲NULL,然後在執行MyApple.ItsSeed-> ItsSeedcoat時嘗試解引用NULL指針。

0

將指針設置爲空之後,對該指針 的任何引用也都爲空。但是,在您的代碼中,您沒有對指針的引用 ;你有兩個完全不同的指針對象, ,你對一個對另一個沒有影響。 (在我認識的每種語言中,這是 。)

0

C++不會實現您所描述的那種行爲。在某些語言中,一個對象會跟蹤所有「弱」指針,這樣當這個對象被釋放時,所有這些指針都會自動爲NULL。然而,C++不是這些語言之一。當一個對象被釋放時,指向該對象的NO指針將自動爲NULL。當某個指向某個對象的特定指針變爲NULL時,不會有其他指向該對象的指針自動變爲NULL。如果您需要這種行爲,請參閱boost::weak_ptrstd::weak_ptr

相關問題