From 85fe2a26e40838e5c03d45c92ea0cd27860a73c2 Mon Sep 17 00:00:00 2001 From: Awin Huang Date: Mon, 6 Jun 2022 11:04:20 +0800 Subject: [PATCH] vault backup: 2022-06-06 11:04:20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Affected files: 02. PARA/03. Resources(資源)/C++17/智慧指標.md --- .../03. Resources(資源)/C++17/智慧指標.md | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/02. PARA/03. Resources(資源)/C++17/智慧指標.md b/02. PARA/03. Resources(資源)/C++17/智慧指標.md index 705cb71..32b9925 100644 --- a/02. PARA/03. Resources(資源)/C++17/智慧指標.md +++ b/02. PARA/03. Resources(資源)/C++17/智慧指標.md @@ -1,8 +1,8 @@ unique_ptr與shared_ptr都是智慧指標,箱對於原本的raw pointer,智慧指標使用起來更方便,也不用擔心delete的問題。 ## unique_ptr -unique_ptr的特點是,它保證在一個時間內,只會有一個指標的擁有者,也就是這個指標不能被複製跟移動,當unique_ptr離開它的scope時候,它所擁有的pointer也隨之被delete。這讓你不用擔心memory leak的問題。 -原本分配記憶體的方法,假設我們有一個class叫BigBuffer: +`unique_ptr`的特點是,它保證在一個時間內,只會有一個指標的擁有者,也就是這個指標不能被複製跟移動,當`unique_ptr`離開它的scope時候,它所擁有的pointer也隨之被delete。這讓你不用擔心memory leak的問題。 +原本分配記憶體的方法,假設我們有一個class叫`BigBuffer`: ```cpp BigBuffer* bigBuf = new BigBuffer(bufferSize); @@ -11,23 +11,23 @@ BigBuffer* bigBuf = new BigBuffer(bufferSize); delete bigBuf; ``` -用unique_ptr: +用`unique_ptr`: ```cpp auto bigBuf = std::make_unique(bufferSize); // Use buffer here // bigBuf will be released when exiting scope ``` -我們統一用`std::make_unique<>`這個template function來建立unique_ptr,角括號<>裡面要帶入你要建立的型別,後面的括號()就是型別的constructor,使用起來跟new是一樣的。 -因為`std::make_unique<>`裡面已經有表明型別了,所以變數就用auto就可以了,不用再寫一次型別。 +我們統一用`std::make_unique<>`這個template function來建立`unique_ptr`,角括號`<>`裡面要帶入你要建立的型別,後面的括號`()`就是型別的constructor,使用起來跟new是一樣的。 +因為`std::make_unique<>`裡面已經有表明型別了,所以變數就用`auto`就可以了,不用再寫一次型別。 -一旦unique_ptr建立之後,使用起來就跟一般指標沒有兩樣,都是用`->`來操作:`bigBuf->setXXX()` or `bigBuf->getXXX()`。 -但是別忘記unique_ptr本身還是一個local variable,所以我們可以用`.`來操作unique_ptr,例如我們可以用`.reset()`重新配一個指標: +一旦`unique_ptr`建立之後,使用起來就跟一般指標沒有兩樣,都是用`->`來操作:`bigBuf->setXXX()` or `bigBuf->getXXX()`。 +但是別忘記`unique_ptr`本身還是一個local variable,所以我們可以用`.`來操作`unique_ptr`,例如我們可以用`.reset()`重新配一個指標: ```cpp bigBuf.reset(std::make_unique(bufferSizeLarger)); ``` -這時候舊指標會自動delete,然後指向新的指標(如果記憶體分配有成功的話),或者指向nullptr(記憶體分配失敗)。 -如果單純想要釋放指標,那就單純的reset就好。 +這時候舊指標會自動delete,然後指向新的指標(如果記憶體分配有成功的話),或者指向`nullptr`(記憶體分配失敗)。 +如果單純想要釋放指標,那就單純的呼叫`reset()`就好。 ```cpp bigBuf.reset(); // Now I'm nullptr ``` @@ -42,12 +42,20 @@ auto intArray = std::make_unique(1024); intArray[5] = 555; ``` -不過對於陣列的操作現在更建議使用std::array。 +不過對於陣列的操作現在更建議使用`std::array`。 -如果有什麼特殊原因讓你決定不再讓unique_ptr蘭幫你管理指標,可以用`release`來讓出指標: +如果有什麼特殊原因讓你決定不再讓`unique_ptr`來幫你管理指標,可以用`release()`來讓出指標: ```cpp auto intArray = std::make_unique(1024); -int* intArrayRaw = +int* intArrayRaw = intArray.release(); // Now I don't care anymore +``` +但是這時候呼叫`delete[]`(或`delete`)的責任又回到你身上了。所以千萬不要把`release()`跟`reset()`搞混了。 + +`unique_ptr`不能被複製跟移動,所以下列的寫法都編不過: +```cpp +std::unique_ptr ptr2(ptr1); // Error +std::unique_ptr ptr2 = ptr1; // Error ``` + ## shared_ptr \ No newline at end of file