為什麼使用指標比使用物件本身更好?
問題:為什麼使用指標比使用物件本身更好?
我是一名Java程式設計師,最近開始學習使用C++中的物件。有個問題我一直覺得很困惑:那就是為什麼人們更喜歡使用指向物件的指標而不是物件本身。比如:
這樣宣告:Object *myObject = new Object;
而不是:Object myObject;
使用函式的時候也是如此,假設有個函式為testFunc(),使用時可以這樣:
myObject.testFunc();
但一般這樣呼叫:
myObject->testFunc();
但是我不知道為什麼要這樣做,我想可能是因為我們直接訪問了記憶體地址,所以能提高效率和執行速度。我理解的對嗎?
最佳答案:
很不幸,你看的很多講的都是動態分配。這隻能說明存在很多根本不精通C++的程式設計師。從某種意義上說,你的問題其實可以分成兩個小問題。第一個是應該何時使用動態分配(即使用new關鍵字)?第二個問題是應該何時使用指標?
使用合適的工具通常是做好一項工作的關鍵。在大部分情況下,存在比使用一般的動態分配或者原指標更合適、更安全的方法。
動態分配
在你的問題裡,你用了兩種方式建立物件。這兩種方式主要的不同在於物件的儲存時間。當執行Object myObject;這句程式碼時,它作為自動變數被建立,這意味著當物件出了作用域時也會自動銷燬。而當你使用new Object()這種方式時,物件所擁有的記憶體是動態分配的,這表示直到你呼叫delete()方法物件才會被銷燬,否則一直存在。當需要用動態分配記憶體來處理時,你應該只使用動態分配的方式,也就是說,當你可以使用動態分配記憶體的時候就不要使用自動變數。
以下是可能會使用到動態分配的兩種常見情況:
1.當想讓物件在出了作用域後依然存在——且確實就是之前儲存在該記憶體中的物件,而不是物件的拷貝。如果你可以接受使用物件的拷貝或者移動(大部分情況下你應該這樣),那麼你更應該使用自動儲存方式。
2. 當需要大量記憶體時,這種情況下極易導致棧溢位。當然如果這對你來說根本不是問題就更好了(大部分情況下這是不可能的)。這顯然超出了C++的管轄範圍,但是不幸的是,我們必須處理我們開發的系統中存在的這種現實問題。
當你確實需要使用動態分配時,你應該將它封裝到一個智慧指標中或者其他能具有RAII特性的型別(例如標準容器)。智慧指標提供動態分配記憶體的物件的所有權語義。例如std::unique_ptr和std::shared_ptr。如果你能夠合適的使用它,你基本上不需要自己管理記憶體(參見Rule of Zero這篇文章)。
指標
事實上,指標除了用來實現動態分配記憶體外還有很多其它的用法,但是其中大部分也都存在比它們更好的選擇。就像前面說過的那樣,除非你必須用到指標,否則不要貿然使用。
需要使用引用的情況:有的時候,你想呼叫的函式需要訪問你當前的物件本身(而不是它的拷貝),那麼你就需要使用指標作為引數進行傳遞(暫不論它是如何分配的)。然而,在大部分情況下,使用引用會比指標更好,這也正是引用被設計的理由。注意一下,這裡不需要像上面所說的那樣去延長物件的生命週期。前面已經說過了,如果你能接受使用物件的拷貝,那麼你就沒必要再使用引用了。
需要使用多型的情況:通常你只能通過物件的指標或者引用來實現多型(也就是根據物件的動態型別來呼叫函式)。如果這就是你想要的,那麼你就需要使用指標或者引用。同樣,以指標為優先選擇。
當物件可忽略時,通過傳遞一個空指標來實現物件是可選的屬性:如果它是一個引數的話,你應該優先使用預設引數或者函式過載的方法。否則你應該選擇一種可以封裝這種行為的型別,例如boost::optional(或者是std::optional)。
當你想降低檔案間的編譯依存關係從而節省時間:指標的一大特點在於你只需要在前面宣告一下指標指向的型別(而如果要使用實際的物件,你還需要定義一下)。這樣你就能降低你的編譯單元之間的耦合性從而減少編譯時間。參考Pimpl idiom.
當你想呼叫C或者類似C風格的函式庫的介面時:在這種情況下,你不得不使用指標進行操作。你唯一能做的事情就是要保證你的指標在不使用時要被釋放。你也能通過智慧指標來操作原指標,例如通過它來呼叫成員函式。如果被呼叫庫已經為你申請了空間而又希望你通過控制程式碼來釋放的話,利用智慧指標封裝起控制程式碼並利用定製的析構器來釋放記憶體無疑是一種合理的選擇。
原文連結: stackoverflow 翻譯: 伯樂線上 - Licorice
相關文章
- C++中為什麼使用指標比使用物件本身更好?C++指標物件
- C++中為什麼要用指標,而不直接使用物件?C++指標物件
- 什麼是智慧指標?為什麼要用智慧指標?指標
- Go語言什麼時候該使用指標 與 指標使用分析Go指標
- 為什麼REST比GraphQL更好? - TomaszJaskuλaREST
- xm外匯中atr指標使用技巧有什麼?指標
- 為什麼Kotlin比任何愚蠢的語言更好Kotlin
- Go高階特性 12 | 指標詳解:在什麼情況下應該使用指標?Go指標
- 為什麼 APISIX Ingress 是比 Traefik 更好的選擇?API
- 為什麼使用縮排來分組語句?15個為什麼,幫助你更好的理解Python!Python
- 為什麼iPhone拍照更好看iPhone
- 為什麼使用Sails?AI
- 第十一章:使用智慧指標管理物件資源指標物件
- Java面試題:為什麼HashMap不建議使用物件作為Key?Java面試題HashMap物件
- 為什麼 APISIX Ingress 是比 Ingress NGINX 更好的選擇?APINginx
- 什麼是Docker?為什麼使用docker?Docker
- 什麼是JSON?如何使用?它比BSON更好嗎?JSON
- 什麼是介面?為什麼使用介面? 什麼時候使用介面?(轉)
- 為什麼使用API?什麼情況下避免使用API?API
- 為什麼在BI應用中,指標管理是重中之重指標
- Flutter為什麼使用Dart?FlutterDart
- 為什麼要使用 Redis?Redis
- 我為什麼使用 JavaJava
- 為什麼使用PythonPython
- 為什麼要使用promisePromise
- 為什麼使用NativeJdbcExtractorJDBC
- 為什麼要使用框架框架
- 為什麼要使用Docker?Docker
- 為什麼要使用EntityBeanBean
- 使用指標接收器時,值物件自動取指標的奇怪問題指標物件
- 為什麼說無程式碼開發比低程式碼開發更好?
- 為什麼Java在高速交易系統上比C ++更好? -efinancialcareersJavaNaN
- C\C++語言重點——指標篇 | 為什麼指標被譽為 C 語言靈魂?(一文讓你完全搞懂指標)C++指標
- TypeScript是什麼,為什麼要使用它?TypeScript
- 中國企業為什麼需要以指標為核心的ABI平臺?指標
- C#中使用指標C#指標
- Swift 中的指標使用Swift指標
- C語言指標安全及指標使用問題C語言指標