diff --git a/02. PARA/03. Resources(資源)/C++17/rvalue.md b/02. PARA/03. Resources(資源)/C++17/rvalue.md index 1be6fa8..a8c2cd9 100644 --- a/02. PARA/03. Resources(資源)/C++17/rvalue.md +++ b/02. PARA/03. Resources(資源)/C++17/rvalue.md @@ -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) \ No newline at end of file