名前空間
変種
操作

std::move

提供: cppreference.com
< cpp‎ | utility
 
 
 
ヘッダ <utility> で定義
template< class T >
typename std::remove_reference<T>::type&& move( T&& t ) noexcept;
(C++11およびそれ以降)
(C++14以前)
template< class T >
constexpr typename std::remove_reference<T>::type&& 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 (一時オブジェクトなど) または xvalue (std::move によって生成されたものなど) のいずれか) を指定して呼んだとき、オーバーロード解決によって選択されます。 引数がリソースを所有するオブジェクトを表す場合、これらのオーバーロードは、引数が保持しているあらゆるリソースをムーブするためのオプションを持ちます (しかしそれが要求されるわけではありません)。 例えば、連結リストのムーブコンストラクタは、個々のノードを確保してコピーする代わりに、リストの先頭を指すポインタをコピーし、引数に nullptr を格納することができます。

右辺値参照変数の名前は左辺値であり、右辺値参照引数を取る関数オーバーロードに束縛されるためには xvalue に変換されなければなりません。 これはムーブコンストラクタムーブ代入演算子がなぜ一般的に 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()
str.clear(); // OK, clear() has no preconditions

また、 xvalue 引数を指定して呼ばれた標準ライブラリの関数は、引数がオブジェクトへの唯一の参照であると仮定することがあります。 std::move で左辺値から構築された場合、エイリアシングチェックは行われません。 これは、標準ライブラリのムーブ代入演算子は自己代入チェックを行う必要がないことを意味します。

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

[編集]

#include <iostream>
#include <utility>
#include <vector>
#include <string>
 
int main()
{
    std::string str = "Hello";
    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 \"" << 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 \"" << str << "\"\n";
 
    std::cout << "The contents of the vector are \"" << v[0]
                                         << "\", \"" << v[1] << "\"\n";
}

出力例:

After copy, str is "Hello"
After move, str is ""
The contents of the vector are "Hello", "Hello"

[編集] 関連項目

(C++11)
関数の引数を転送します
(関数テンプレート) [edit]
ムーブコンストラクタが例外を投げない場合、右辺値参照を取得します
(関数テンプレート) [edit]
(C++11)
指定範囲の要素を新しい位置にムーブします
(関数テンプレート) [edit]