Namespaces
Variants

std:: move

From cppreference.net
Utilities library
定義先ヘッダ <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 はその引数 t を識別する xvalue式 を生成します。これは右辺値参照型への static_cast と完全に等価です。

目次

パラメータ

t - 移動対象のオブジェクト

戻り値

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

注記

右辺値参照パラメータを受け入れる関数( ムーブコンストラクタ ムーブ代入演算子 、および std::vector::push_back のような通常のメンバ関数を含む)は、 オーバーロード解決 によって、 右辺値 引数(一時オブジェクトのような prvalue や、 std::move によって生成される xvalue など)で呼び出されたときに選択されます。引数がリソースを所有するオブジェクトを識別する場合、これらのオーバーロードは、引数によって保持されているリソースを ムーブ するオプションを持ちますが、必須ではありません。例えば、リンクリストのムーブコンストラクタは、リストの先頭へのポインタをコピーし、個々のノードを割り当ててコピーする代わりに、引数に nullptr を格納するかもしれません。

rvalue reference の変数名は lvalues であり、 xvalues に変換する必要があるため、rvalue referenceパラメータを受け入れる関数オーバーロードにバインドされます。これが、 move constructors move assignment operators が通常 std::move を使用する理由です:

// シンプルなムーブコンストラクタ
A(A&& arg) : member(std::move(arg.member)) // 式 "arg.member" は左辺値
{}
// シンプルなムーブ代入演算子
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は有効だが未指定の状態になる
str.back(); // size() == 0の場合未定義動作: back()には事前条件 !empty()がある
if (!str.empty())
    str.back(); // OK, empty()には事前条件がなく、back()の事前条件が満たされている
str.clear(); // OK, clear()には事前条件がない

また、xvalue引数で呼び出された標準ライブラリ関数は、その引数がオブジェクトへの唯一の参照であると仮定する場合があります。もしその引数がlvalueから std::move で構築された場合、エイリアシングチェックは行われません。しかし、標準ライブラリ型の自己ムーブ代入は、オブジェクトを有効な(ただし通常は未指定の)状態にすることが保証されています:

std::vector<int> v = {2, 3, 3};
v = std::move(v); // vの値は不定

#include <iomanip>
#include <iostream>
#include <string>
#include <utility>
#include <vector>
int main()
{
    std::string str = "Salut";
    std::vector<std::string> v;
    // push_back(const T&) オーバーロードを使用
    // 文字列のコピーコストが発生する
    v.push_back(str);
    std::cout << "After copy, str is " << std::quoted(str) << '\n';
    // 右辺値参照 push_back(T&&) オーバーロードを使用
    // 文字列のコピーは発生せず、代わりにstrの内容が
    // ベクターに移動される。コストは低いが、
    // strが空になる可能性がある
    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)
関数の引数を転送し、テンプレート引数の型を使用して値カテゴリを保持する
(function template)
ムーブコンストラクタが例外を投げない場合、引数をxvalueに変換する
(function template)
(C++11)
要素の範囲を新しい位置にムーブする
(function template)