Files
Obsidian-Main/02. PARA/03. Resources(資源)/C++17/智慧指標.md
Awin Huang 85fe2a26e4 vault backup: 2022-06-06 11:04:20
Affected files:
02. PARA/03. Resources(資源)/C++17/智慧指標.md
2022-06-06 11:04:20 +08:00

61 lines
2.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
unique_ptr與shared_ptr都是智慧指標箱對於原本的raw pointer智慧指標使用起來更方便也不用擔心delete的問題。
## unique_ptr
`unique_ptr`的特點是,它保證在一個時間內,只會有一個指標的擁有者,也就是這個指標不能被複製跟移動,當`unique_ptr`離開它的scope時候它所擁有的pointer也隨之被delete。這讓你不用擔心memory leak的問題。
原本分配記憶體的方法假設我們有一個class叫`BigBuffer`
```cpp
BigBuffer* bigBuf = new BigBuffer(bufferSize);
// Use buffer here
delete bigBuf;
```
`unique_ptr`
```cpp
auto bigBuf = std::make_unique<BigBuffer>(bufferSize);
// Use buffer here
// bigBuf will be released when exiting scope
```
我們統一用`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()`重新配一個指標:
```cpp
bigBuf.reset(std::make_unique<BigBuffer>(bufferSizeLarger));
```
這時候舊指標會自動delete然後指向新的指標如果記憶體分配有成功的話或者指向`nullptr`(記憶體分配失敗)。
如果單純想要釋放指標,那就單純的呼叫`reset()`就好。
```cpp
bigBuf.reset(); // Now I'm nullptr
```
如果要分配陣列的話:
```cpp
auto intArray = std::make_unique<int[]>(1024);
```
使用方式也是一樣的:
```cpp
intArray[5] = 555;
```
不過對於陣列的操作現在更建議使用`std::array`
如果有什麼特殊原因讓你決定不再讓`unique_ptr`來幫你管理指標,可以用`release()`來讓出指標:
```cpp
auto intArray = std::make_unique<int[]>(1024);
int* intArrayRaw = intArray.release(); // Now I don't care anymore
```
但是這時候呼叫`delete[]`(或`delete`)的責任又回到你身上了。所以千萬不要把`release()``reset()`搞混了。
`unique_ptr`不能被複製跟移動,所以下列的寫法都編不過:
```cpp
std::unique_ptr<int> ptr2(ptr1); // Error
std::unique_ptr<int> ptr2 = ptr1; // Error
```
## shared_ptr