名稱空間
變體
操作

std::move

來自 cppreference.com
< cpp‎ | 工具
 
 
 
在標頭檔案 <utility> 中定義
template< class T >
typename std::remove_reference<T>::type&& move( T&& t ) noexcept;
(C++11 起)
(直到 C++14)
template< class T >
constexpr std::remove_reference_t<T>&& move( T&& t ) noexcept;
(C++14 起)

std::move 用於指示物件 t 可以被“移動”,即允許將資源從 t 高效地轉移到另一個物件。

特別是,std::move 產生一個 xvalue 表示式,它標識其引數 t。它與對右值引用型別進行 static_cast 完全等價。

目錄

[編輯] 引數

t - 要移動的物件

[編輯] 返回值

static_cast<typename std::remove_reference<T>::type&&>(t)

[編輯] 注意

接受右值引用引數的函式(包括 移動建構函式移動賦值運算子 以及 std::vector::push_back 等常規成員函式)在被呼叫時,如果傳入 右值 引數(無論是 純右值,例如臨時物件,還是 亡值,例如由 std::move 產生的值),會透過 過載決議 被選中。如果引數標識一個擁有資源的物件,這些過載可以選擇(但並非必須)移動引數所持有的任何資源。例如,連結串列的移動建構函式可能會複製指向連結串列頭部的指標,並在引數中儲存 nullptr,而不是分配和複製單個節點。

右值引用 變數的名稱是 左值,必須轉換為 亡值 才能繫結到接受右值引用引數的函式過載,這就是 移動建構函式移動賦值運算子 通常使用 std::move 的原因。

// Simple move constructor
A(A&& arg) : member(std::move(arg.member)) // the expression "arg.member" is lvalue
{}
 
// Simple move assignment operator
A& operator=(A&& other)
{
    member = std::move(other.member);
    return *this;
}

一個例外是當函式引數的型別是 轉發引用(看起來像型別模板引數的右值引用)時,在這種情況下,使用 std::forward 代替。

除非另有說明,所有被移動的標準庫物件都處於“有效但未指定的狀態”,這意味著物件的類不變數保持(因此不帶前置條件的函式,例如賦值運算子,可以在物件被移動後安全地使用)。

std::vector<std::string> v;
std::string str = "example";
v.push_back(std::move(str)); // str is now valid but unspecified
str.back(); // undefined behavior if size() == 0: back() has a precondition !empty()
if (!str.empty())
    str.back(); // OK, empty() has no precondition and back() precondition is met
 
str.clear(); // OK, clear() has no preconditions

此外,以亡值引數呼叫的標準庫函式可能會假設該引數是物件的唯一引用;如果它是用 std::move 從左值構造的,則不進行別名檢查。但是,標準庫型別的自移動賦值保證將物件置於有效(但通常未指定)狀態。

std::vector<int> v = {2, 3, 3};
v = std::move(v); // the value of v is unspecified

[編輯] 示例

#include <iomanip>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
 
int main()
{
    std::string str = "Salut";
    std::vector<std::string> v;
 
    // uses the push_back(const T&) overload, which means
    // we'll incur the cost of copying str
    v.push_back(str);
    std::cout << "After copy, str is " << std::quoted(str) << '\n';
 
    // uses the rvalue reference push_back(T&&) overload,
    // which means no strings will be copied; instead, the contents
    // of str will be moved into the vector. This is less
    // expensive, but also means str might now be empty.
    v.push_back(std::move(str));
    std::cout << "After move, str is " << std::quoted(str) << '\n';
 
    std::cout << "The contents of the vector are {" << std::quoted(v[0])
              << ", " << std::quoted(v[1]) << "}\n";
}

可能的輸出

After copy, str is "Salut"
After move, str is ""
The contents of the vector are {"Salut", "Salut"}

[編輯] 參見

(C++11)
轉發函式引數並使用型別模板引數來保留其值類別
(函式模板) [編輯]
如果移動建構函式不丟擲異常,則將引數轉換為亡值
(函式模板) [編輯]
(C++11)
將一個範圍的元素移動到一個新位置
(函式模板) [編輯]