文章目錄
- 一、移動語義
- 1、為什么需要移動語義?
- 2、怎么“偷”?——右值引用(`&&`)
- 3、如何實現移動語義?——移動構造函數/賦值
- 4、什么時候觸發移動?
- 5、移動 vs 拷貝
一、移動語義
1、為什么需要移動語義?
傳統拷貝(
=
)會復制整個對象,但如果對象很大(如vector<string>
),拷貝開銷大。
移動語義的核心思想:“偷資源”,避免不必要的深拷貝,提升性能。
2、怎么“偷”?——右值引用(&&
)
- 右值(臨時對象、字面量等) 的生命周期短,可以安全“偷”它的資源。
- 右值引用
&&
用來綁定右值,表示“這個值可以移動”。
示例:
std::string s1 = "Hello";
std::string s2 = std::move(s1); // 把 s1 的資源“偷”給 s2
s1
變成空(資源被移動),s2
直接接管原內存,沒有拷貝。
3、如何實現移動語義?——移動構造函數/賦值
類需要定義移動構造函數和移動賦值運算符:
class MyObject {
public:// 移動構造函數(參數是右值引用)MyObject(MyObject&& other) noexcept {data_ = other.data_; // 直接“偷”指針other.data_ = nullptr; // 原對象置空}// 移動賦值運算符MyObject& operator=(MyObject&& other) noexcept {if (this != &other) {delete data_; // 釋放自己的資源data_ = other.data_; // “偷”對方的資源other.data_ = nullptr;}return *this;}private:int* data_; // 假設管理動態內存
};
關鍵點:
- 直接“竊取”資源(如指針),避免深拷貝。
- 把原對象的資源置空(防止重復釋放)。
4、什么時候觸發移動?
- 顯式移動:
std::move(obj)
強制轉成右值引用。 - 隱式移動:函數返回臨時對象時(編譯器優化)。
示例:
std::vector<int> createBigVector() {std::vector<int> v = {1, 2, 3, 4, 5};return v; // 編譯器可能優化為移動(而非拷貝)
}auto v = createBigVector(); // 移動構造,無拷貝
5、移動 vs 拷貝
拷貝 | 移動 | |
---|---|---|
操作 | 深復制(完整備份) | “偷”資源(直接接管) |
開銷 | 高(內存、時間) | 低(僅指針交換) |
原對象 | 保持不變 | 被置空(資源轉移) |
一句話總結:
移動語義通過
&&
和std::move
“偷”臨時對象的資源,避免深拷貝,提升性能。適用于管理動態內存的類(如vector
、string
、自定義資源類)。