在寫C++過程中,指標的使用與操作是最頻繁被使用的,有些難解的bug,通常point佔絕大多數,這裡複習一個很基本的概念。
如下面的例子,個別使用兩個a指標,也各自呼叫他們的member function test(),發覺都可以印出test的字串,但為什麼第一個指標明明是指向undefine的空間,為什麼不會出現問題呢,不是應該要出現Segmentation Fault嗎?
這裡隱藏一個很重要,也很容易被誤解的觀念,通常使用null point或不知指向何處的point時,操作member function是不會發生Segmentation Fault的,會產生Segmentation Fault是在操作它的member時,如果下面的程式碼多加上一段a->value的話,當程式運行到這一行就會發生crash了。
如下面的例子,個別使用兩個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 就會非常的重要。
全站熱搜
留言列表