vault backup: 2022-06-09 14:50:27

Affected files:
.obsidian/workspace
02. PARA/03. Resources(資源)/C++17/rvalue.md
02. PARA/03. Resources(資源)/C++17/智慧指標.md
This commit is contained in:
2022-06-09 14:50:27 +08:00
parent a7a1b5b650
commit 5d6888028a
3 changed files with 29 additions and 22 deletions

12
.obsidian/workspace vendored
View File

@@ -10,7 +10,7 @@
"state": { "state": {
"type": "markdown", "type": "markdown",
"state": { "state": {
"file": "02. PARA/03. Resources資源/C++17/智慧指標.md", "file": "02. PARA/03. Resources資源/C++17/rvalue.md",
"mode": "source", "mode": "source",
"source": true "source": true
} }
@@ -23,7 +23,7 @@
"state": { "state": {
"type": "outline", "type": "outline",
"state": { "state": {
"file": "02. PARA/03. Resources資源/C++17/智慧指標.md" "file": "02. PARA/03. Resources資源/C++17/rvalue.md"
} }
} }
} }
@@ -81,7 +81,7 @@
"state": { "state": {
"type": "backlink", "type": "backlink",
"state": { "state": {
"file": "02. PARA/03. Resources資源/C++17/智慧指標.md", "file": "02. PARA/03. Resources資源/C++17/rvalue.md",
"collapseAll": true, "collapseAll": true,
"extraContext": true, "extraContext": true,
"sortOrder": "alphabetical", "sortOrder": "alphabetical",
@@ -125,15 +125,15 @@
}, },
"active": "94f0e8a81af6c9e2", "active": "94f0e8a81af6c9e2",
"lastOpenFiles": [ "lastOpenFiles": [
"02. PARA/03. Resources資源/C++17/智慧指標.md",
"02. PARA/03. Resources資源/C++17/rvalue.md", "02. PARA/03. Resources資源/C++17/rvalue.md",
"02. PARA/03. Resources資源/C++17/move operator.md",
"02. PARA/03. Resources資源/C++17/智慧指標.md",
"00. TOP/01. TODO.md", "00. TOP/01. TODO.md",
"02. PARA/03. Resources資源/git/submodule.md", "02. PARA/03. Resources資源/git/submodule.md",
"02. PARA/03. Resources資源/git.md", "02. PARA/03. Resources資源/git.md",
"02. PARA/01. Project專案/008. Sentinel.md", "02. PARA/01. Project專案/008. Sentinel.md",
"02. PARA/03. Resources資源/C++17/lvalue.md", "02. PARA/03. Resources資源/C++17/lvalue.md",
"02. PARA/03. Resources資源/FFMPEG/01. Setup.md", "02. PARA/03. Resources資源/FFMPEG/01. Setup.md",
"02. PARA/03. Resources資源/FFMPEG/00. Introduction.md", "02. PARA/03. Resources資源/FFMPEG/00. Introduction.md"
"02. PARA/03. Resources資源/FFMpeg.md"
] ]
} }

View File

@@ -17,8 +17,8 @@ int b = 5;
int& c = a + b; int& c = a + b;
``` ```
因為`a+b`是一個rvalue臨時的值沒辦法取址所以無法參考。 因為`a+b`是一個 rvalue臨時的值沒辦法取址所以無法參考。
但是可以用`&&`來參考rvalue。例如 但是可以用`&&`來參考 rvalue。例如
```cpp ```cpp
int a = 10; int a = 10;
int b = 5; int b = 5;
@@ -33,10 +33,10 @@ int r = a + b;
int& c = r; int& c = r;
``` ```
了解rvalue reference之後就可以實作類別的 move constructor 跟move assignment operator。這可以減少複製的成本。 了解 rvalue reference 之後,就可以實作類別的 move constructor 跟 move assignment operator。這可以減少複製的成本。
## Move constructor ## Move constructor
假設我們有一個classBigBuffer定義如下 假設我們有一個 classBigBuffer定義如下
```cpp ```cpp
class BigBuffer { class BigBuffer {
public: public:
@@ -72,7 +72,7 @@ private:
}; };
``` ```
這個class的特色就是每一次使用都會佔用100MB的記憶體空間想像下面的程式的動作 這個 class 的特色就是每一次使用都會佔用100MB的記憶體空間想像下面的程式的動作
```cpp ```cpp
BigBuffer buf1; BigBuffer buf1;
// Do something with buf1 // Do something with buf1
@@ -87,7 +87,7 @@ BigBuffer copy constructor, copy 104857600Bytes // copy buf1 to buf2
... ...
``` ```
這會先產生buf1然後把buf1 copybuf2。如果我們想要省下copy的成本這時候 Move constructor 就可以派上用場了。 這會先產生 buf1然後把 buf1 copybuf2。如果我們想要省下 copy 的成本,這時候 Move constructor 就可以派上用場了。
幫 BigBuffer 加一個 Move constructor 幫 BigBuffer 加一個 Move constructor
```cpp ```cpp
class BigBuffer { class BigBuffer {
@@ -106,9 +106,9 @@ public:
}; };
``` ```
這個 move constructor 的參數就是一個 rvalue reference我們把來源的 bufferSize 跟 buffer指標「移到」我們這邊而不是完整的複製一份。在轉移之後呢當然也要把來源清空讓轉移更加明確。 這個 move constructor 的參數就是一個 rvalue reference我們把來源的 bufferSize 跟 buffer 指標「移到」我們這邊,而不是完整的複製一份。在轉移之後呢,當然也要把來源清空,讓轉移更加明確。
有了 Move assignment operator 之後,在執行一次原本的程式,你會發現訊息......沒有變,還是一樣呼叫 copy constructor 來複製了100MBbuffer這時我們需要明確的告訴 compiler 我們要「移動」物件,而不是複製它,把原本的程式改為: 有了 Move assignment operator 之後,在執行一次原本的程式,你會發現訊息......沒有變,還是一樣呼叫 copy constructor 來複製了100MBbuffer這時我們需要明確的告訴 compiler 我們要「移動」物件,而不是複製它,把原本的程式改為:
```cpp ```cpp
BigBuffer buf1; BigBuffer buf1;
// Do something with buf1 // Do something with buf1
@@ -123,7 +123,7 @@ BigBuffer move constructor // move buf1 to buf2, buf1 has nullptr now
... ...
``` ```
另外一個情形也可以受益於此假如我們有個function會產生 BigBuffer如下 另外一個情形也可以受益於此,假如我們有個 function 會產生 `BigBuffer`,如下:
```cpp ```cpp
BigBuffer BigBufferCreator() { BigBuffer BigBufferCreator() {
std::cout << "BigBufferCreator: Create a BigBuffer!\n"; std::cout << "BigBufferCreator: Create a BigBuffer!\n";
@@ -136,7 +136,7 @@ BigBuffer BigBufferCreator() {
BigBuffer b = BigBufferCreator(); // copy tempb to b BigBuffer b = BigBufferCreator(); // copy tempb to b
``` ```
在沒有Move constructor的情況下上面的程式會先產生一個 tempb然後複製給 b,訊息: 在沒有 Move constructor 的情況下,上面的程式會先產生一個 `tempb`,然後複製給 `b`,訊息:
``` ```
BigBufferCreator: Create a BigBuffer! BigBufferCreator: Create a BigBuffer!
BigBuffer constructor BigBuffer constructor
@@ -145,7 +145,7 @@ BigBuffer copy constructor, copy 104857600Bytes // Copy 100MB!
... ...
``` ```
在有Move constructor的情況下訊息就變成 在有 Move constructor 的情況下,訊息就變成:
``` ```
BigBufferCreator: Create a BigBuffer! BigBufferCreator: Create a BigBuffer!
BigBuffer constructor BigBuffer constructor
@@ -155,10 +155,10 @@ BigBuffer destructor
BigBuffer destructor BigBuffer destructor
``` ```
因為 `BigBufferCreator()` 產生的就是一個 BigBuffer rvalue所以 compiler會使用 move constructor`BigBuffer(BigBuffer&& src)` 而不是 copy constructor。 因為 `BigBufferCreator()` 產生的就是一個 `BigBuffer` rvalue所以 compiler 會使用 move constructor`BigBuffer(BigBuffer&& src)` 而不是 copy constructor。
## Move assignment operator(`=`) ## Move assignment operator(`=`)
Move assignment operator 的行為跟 move constructor 是一樣的,幫 BigBuffer 加入 move assignment operator Move assignment operator 的行為跟 move constructor 是一樣的,幫 `BigBuffer` 加入 move assignment operator
```cpp ```cpp
class BigBuffer { class BigBuffer {
public: public:
@@ -196,8 +196,15 @@ BigBuffer b1, b2;
b2 = std::move(b1); b2 = std::move(b1);
``` ```
這樣就可以了。 這樣就可以了。訊息:
```
BigBuffer constructor
BigBuffer constructor
BigBuffer move operator // Use MOVE!
```
## 參考 ## 參考
- [Value categories - cppreference.com](https://en.cppreference.com/w/cpp/language/value_category) - [Value categories - cppreference.com](https://en.cppreference.com/w/cpp/language/value_category)
- [rvalue 參考](https://openhome.cc/Gossip/CppGossip/RvalueReference.html) - [rvalue 參考](https://openhome.cc/Gossip/CppGossip/RvalueReference.html)
- [Move constructors - cppreference.com](https://en.cppreference.com/w/cpp/language/move_constructor)
- [Move assignment operator - cppreference.com](https://en.cppreference.com/w/cpp/language/move_assignment)

View File

@@ -68,7 +68,7 @@ auto ptr1 = std::make_unique<int>(5);
auto anotherPtr = std::move(ptr1); auto anotherPtr = std::move(ptr1);
``` ```
ptr1原本所管理的指標會轉移給 anotherPtr ptr1原本所管理的指標會轉移給 anotherPtrptr1 會變成 nullptr。
## shared_ptr ## shared_ptr
建立一個 `shared_ptr` 是使用[`std::make_shared()`](https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared) 建立一個 `shared_ptr` 是使用[`std::make_shared()`](https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared)