vault backup: 2022-06-09 14:30:26

Affected files:
02. PARA/03. Resources(資源)/C++17/rvalue.md
This commit is contained in:
2022-06-09 14:30:26 +08:00
parent bf8ebd3a93
commit 886122f8da

View File

@@ -33,7 +33,7 @@ int r = a + b;
int& c = r;
```
了解rvalue reference之後就可以實作類別的 move constructor 跟move assignment operator。
了解rvalue reference之後就可以實作類別的 move constructor 跟move assignment operator。這可以減少複製的成本。
## Move constructor
假設我們有一個class叫BigBuffer定義如下
@@ -103,6 +103,7 @@ public:
src.bufferSize = 0;
}
...
};
```
這個 move constructor 的參數就是一個 rvalue reference我們把來源的 bufferSize 跟 buffer指標「移到」我們這邊而不是完整的複製一份。在轉移之後呢當然也要把來源清空讓轉移更加明確。
@@ -140,15 +141,57 @@ BigBuffer b = BigBufferCreator(); // copy tempb to b
BigBufferCreator: Create a BigBuffer!
BigBuffer constructor
BigBufferCreator: return
BigBuffer copy constructor, copy 104857600Bytes
BigBuffer copy constructor, copy 104857600Bytes // Copy 100MB!
...
```
在有Move constructor的情況下訊息就變成
```
BigBufferCreator: Create a BigBuffer!
BigBuffer constructor
BigBufferCreator: return
BigBuffer move constructor // Use MOVE!
BigBuffer destructor
BigBuffer destructor
```
因為 `BigBufferCreator()` 產生的就是一個 BigBuffer rvalue所以 compiler會使用 move constructor`BigBuffer(BigBuffer&& src)` 而不是 copy constructor。
## Move assignment operator(`=`)
Move assignment operator 的行為跟 move constructor 是一樣的,幫 BigBuffer 加入 move assignment operator
```cpp
class BigBuffer {
public:
...
BigBuffer& operator=(BigBuffer&& src) noexcept {
std::cout << "BigBuffer move operator\n";
bufferSize = src.bufferSize;
buffer = std::move(src.buffer);
src.buffer.reset();
src.bufferSize = 0;
return *this;
}
...
};
```
測試程式:
```cpp
BigBuffer b1, b2;
b2 = b1;
```
訊息:
```
BigBuffer constructor
BigBuffer constructor
BigBuffer copy operator, copy 104857600Bytes
```
還是使用 copy operator
## 參考
- [Value categories - cppreference.com](https://en.cppreference.com/w/cpp/language/value_category)
- [rvalue 參考](https://openhome.cc/Gossip/CppGossip/RvalueReference.html)