對於原來會C#、Java,轉而用C++時,總會對C++同時有object、reference、pointer三種機制感到困擾,因為在C#、Java只有object,一切都很單純,但在C++卻很複雜。
在C#如以下的程式
2
foo1僅宣告了一個物件,但卻尚未建立。
foo2才是宣告了一個物件,且建立了foo2物件。
在C++卻必須這樣寫
2
3
4
foo1為指向Foo型別object的pointer,但此時僅有pointer還沒有object,所以等同C#的Foo foo1。
foo2真的是一個object了,相當於C#的Foo foo2 = new Foo();
foo3是一個pointer指向Foo object,此時是一個建立在stack的object,不需手動delete刪除。
foo4是一個pointer指向Foo object,此時是一個建立在heap的object,需手動用delete刪除。
foo1若要繼續指定值
或
皆可
總而言之,若要建立在stack上的object,且要直接用該object,直接Foo foo2即可,若想先宣告一個object variable,等日後看情形使用,則要用pointer的Foo *foo1或Foo *foo3 = &Foo();這種方式。
若要建立在heap上的object,則一律使用pointer的Foo *foo4 = new Foo();這種方式。
那何時要建立在stack?何時要建立在heap呢?
若object屬於local object,其scope僅在function裡,此時應建立在stack。
若object屬於static object,在離開function後,希望該object仍存在,此時應建立在heap,該object會一直等到手動下delete時,才會消失。
這是C++和C#語法很大的差異之處!!我ㄧ開始也很不習慣。
若以sematics(語意)而言,C#和C++何者語意較適當?
回想我們在使用基本型別時,如
此時i這個int object已經建立了,所以C++才模仿基本型別建立的方式使用
符合Bjarne Stroustrup所謂『建立一個和基本型別一樣好用的class』想法,所以語法和基本型別一樣。
C#的想法則是,將型別分成value type和reference type,int屬於value type,固用int i語法,而object屬於reference type,一律使用new語法且建立在heap,因為有GC,所以沒有delete問題。
理解後,兩者都有他的道理!!
何時會用reference呢?
將object傳到function裡,且希望使用polymorphism時,會使用reference,當然此時用pointer亦可,不過習慣上大都使用reference,但不可用object,這樣會造成object slicing,就沒有polymorphism了。
執行結果
73行
將物件傳入function,為了要達成polymorphism,所以用了reference。
何時該使用pointer呢?
將object塞進container且要達成polymorphism時,只能使用pointer!!因為object進入container需copy的動作,但reference不支援copy動作,所以不能使用reference,當然也不能使用object,因為會造成object slicing,如此就沒polymorphism了,70行
就是個例子,vector只能放Student *才能達到polymorphism。
Conclusion
我很早就想寫這一篇了,因為對於我這個C#轉C++的人來說,已經被reference,pointer搞的暈頭轉向,希望藉由這篇經驗的總結,能讓各位在C++的學習上少走些冤枉路。
See Also
(原創) 如何使用pointer和reference達成Polymorphism? (初級) (C++) (OO C++)