在寫C++過程中,指標的使用與操作是最頻繁被使用的,有些難解的bug,通常point佔絕大多數,這裡複習一個很基本的概念。

如下面的例子,個別使用兩個a指標,也各自呼叫他們的member function test(),發覺都可以印出test的字串,但為什麼第一個指標明明是指向undefine的空間,為什麼不會出現問題呢,不是應該要出現Segmentation Fault嗎?

這裡隱藏一個很重要,也很容易被誤解的觀念,通常使用null point或不知指向何處的point時,操作member function是不會發生Segmentation Fault的,會產生Segmentation Fault是在操作它的member時,如果下面的程式碼多加上一段a->value的話,當程式運行到這一行就會發生crash了。
 
class A 
{
  public: void test(){printf("test");}
  int value;
};
                                                                               
int main()
{
  A *a;
  A *aa = new A;
  a->test();
  aa->test();
}
 
 

要先知道 member function 的本質是什麼,事實上, A::test() 經過編譯後,跟底下這個函式是一樣的:                                                                                
 
void test(A *this)  // this 應該用 const 修飾,不過先省略
{
    printf("test");
}
                                                                                

然後呼叫
                                                                               
a->test();  其實就是呼叫 test(a);
aa->test(); 其實就是呼叫 test(aa);
                                                                               
傳進去的 a 或 aa,會變成上面紅色的 this,然後根本沒有被使用
                                                                               
因為在 test 裡面,根本沒用到 A 的 member variable,所以 xx->test() 的 xx 不管它是什麼,都不會出問題,因為那個 xx 根本就沒有用到,更極端一點的寫成 ((A *)(0))->test(); 都可以正常執行。

 但如果把test function裡改寫成
                                                                   
void A::test()
{
    printf("test %d", x);
}
                                                                   
經過編譯之後,就會變成
                                                                   
void test(A *this) { printf("test %d", this->x); }
                                                                   
也就是說,a->test() 這個時候的 a 就會變得很重要,因為需要印到 a->x。
像 a 有經過 new,指向有效的記憶體空間,那 a->x 會是個合法的存取。
但如果 aa 根本沒有 new,它指的空間是無效的,aa->x 就是非法存取了。
                                                                   
結論:
                                                                   
如果你 class 的 member function 沒有用到任何 member variable,其實 xx->yy() 那個 xx 就很不重要就像你原本的 test() 那樣,但只要有用到任何 member variable (絕大部份都會用到吧?),那麼 xx->yy() 的 xx 就會非常的重要。
arrow
arrow
    全站熱搜

    cloudfly 發表在 痞客邦 留言(0) 人氣()