為什么使用指針比使用對象本身更好?
問題:為什么使用指針比使用對象本身更好?
我是一名Java程序員,最近開始學習使用C++中的對象。有個問題我一直覺得很困惑:那就是為什么人們更喜歡使用指向對象的指針而不是對象本身。比如:
這樣聲明:Object *myObject = new Object;
而不是:Object myObject;
使用函數(shù)的時候也是如此,假設有個函數(shù)為testFunc(),使用時可以這樣:
myObject.testFunc();
但一般這樣調用:
myObject->testFunc();
但是我不知道為什么要這樣做,我想可能是因為我們直接訪問了內(nèi)存地址,所以能提高效率和運行速度。我理解的對嗎?
***答案:
很不幸,你看的很多講的都是動態(tài)分配。這只能說明存在很多根本不精通C++的程序員。從某種意義上說,你的問題其實可以分成兩個小問題。***個是應該何時使用動態(tài)分配(即使用new關鍵字)?第二個問題是應該何時使用指針?
使用合適的工具通常是做好一項工作的關鍵。在大部分情況下,存在比使用一般的動態(tài)分配或者原指針更合適、更安全的方法。
動態(tài)分配
在你的問題里,你用了兩種方式創(chuàng)建對象。這兩種方式主要的不同在于對象的存儲時間。當執(zhí)行Object myObject;這句代碼時,它作為自動變量被創(chuàng)建,這意味著當對象出了作用域時也會自動銷毀。而當你使用new Object()這種方式時,對象所擁有的內(nèi)存是動態(tài)分配的,這表示直到你調用delete()方法對象才會被銷毀,否則一直存在。當需要用動態(tài)分配內(nèi)存來處理時,你應該只使用動態(tài)分配的方式,也就是說,當你可以使用動態(tài)分配內(nèi)存的時候就不要使用自動變量。
以下是可能會使用到動態(tài)分配的兩種常見情況:
1.當想讓對象在出了作用域后依然存在——且確實就是之前存儲在該內(nèi)存中的對象,而不是對象的拷貝。如果你可以接受使用對象的拷貝或者移動(大部分情況下你應該這樣),那么你更應該使用自動存儲方式。
2. 當需要大量內(nèi)存時,這種情況下極易導致棧溢出。當然如果這對你來說根本不是問題就更好了(大部分情況下這是不可能的)。這顯然超出了C++的管轄范圍,但是不幸的是,我們必須處理我們開發(fā)的系統(tǒng)中存在的這種現(xiàn)實問題。
當你確實需要使用動態(tài)分配時,你應該將它封裝到一個智能指針中或者其他能具有RAII特性的類型(例如標準容器)。智能指針提供動態(tài)分配內(nèi)存的對象的所有權語義。例如std::unique_ptr和std::shared_ptr。如果你能夠合適的使用它,你基本上不需要自己管理內(nèi)存(參見Rule of Zero這篇文章)。
指針
事實上,指針除了用來實現(xiàn)動態(tài)分配內(nèi)存外還有很多其它的用法,但是其中大部分也都存在比它們更好的選擇。就像前面說過的那樣,除非你必須用到指針,否則不要貿(mào)然使用。
需要使用引用的情況:有的時候,你想調用的函數(shù)需要訪問你當前的對象本身(而不是它的拷貝),那么你就需要使用指針作為參數(shù)進行傳遞(暫不論它是如何分配的)。然而,在大部分情況下,使用引用會比指針更好,這也正是引用被設計的理由。注意一下,這里不需要像上面所說的那樣去延長對象的生命周期。前面已經(jīng)說過了,如果你能接受使用對象的拷貝,那么你就沒必要再使用引用了。
需要使用多態(tài)的情況:通常你只能通過對象的指針或者引用來實現(xiàn)多態(tài)(也就是根據(jù)對象的動態(tài)類型來調用函數(shù))。如果這就是你想要的,那么你就需要使用指針或者引用。同樣,以指針為優(yōu)先選擇。
當對象可忽略時,通過傳遞一個空指針來實現(xiàn)對象是可選的屬性:如果它是一個參數(shù)的話,你應該優(yōu)先使用默認參數(shù)或者函數(shù)重載的方法。否則你應該選擇一種可以封裝這種行為的類型,例如boost::optional(或者是std::optional)。
當你想降低文件間的編譯依存關系從而節(jié)省時間:指針的一大特點在于你只需要在前面聲明一下指針指向的類型(而如果要使用實際的對象,你還需要定義一下)。這樣你就能降低你的編譯單元之間的耦合性從而減少編譯時間。參考Pimpl idiom.
當你想調用C或者類似C風格的函數(shù)庫的接口時:在這種情況下,你不得不使用指針進行操作。你唯一能做的事情就是要保證你的指針在不使用時要被釋放。你也能通過智能指針來操作原指針,例如通過它來調用成員函數(shù)。如果被調用庫已經(jīng)為你申請了空間而又希望你通過句柄來釋放的話,利用智能指針封裝起句柄并利用定制的析構器來釋放內(nèi)存無疑是一種合理的選擇。
原文鏈接: stackoverflow 翻譯: 伯樂在線 - Licorice