std::move
| ヘッダ <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 式 を生成します。これは、rvalue 参照型への static_cast と全く同等です。
目次 |
[編集] パラメーター
| t | - | ムーブするオブジェクト |
[編集] 戻り値
static_cast<typename std::remove_reference<T>::type&&>(t)
[編集] 備考
rvalue 参照パラメーターを受け入れる関数(ムーブコンストラクター、ムーブ代入演算子、および std::vector::push_back などの通常のメンバ関数を含む)は、オーバーロード解決によって、rvalue 引数(一時オブジェクトのような prvalue、または std::move によって生成されるような xvalue のいずれか)で呼び出されたときに選択されます。引数がリソースを所有するオブジェクトを識別する場合、これらのオーバーロードは、引数によって保持されているリソースをムーブするオプションがありますが、必須ではありません。たとえば、リンクリストのムーブコンストラクターは、リストの先頭へのポインターをコピーし、個々のノードを割り当ててコピーする代わりに、引数に nullptr を格納する場合があります。
rvalue 参照変数の名前はlvalueであり、rvalue 参照パラメータを受け入れる関数オーバーロードにバインドされるために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; }
例外の1つは、関数パラメーターの型が転送参照(型テンプレートパラメーターへのrvalue参照のように見える)である場合で、この場合は代わりに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
また、xvalue 引数で呼び出される標準ライブラリ関数は、その引数がオブジェクトへの唯一の参照であると仮定する場合があります。もしそれが std::move を使って lvalue から構築された場合、エイリアシングのチェックは行われません。ただし、標準ライブラリ型の自己ムーブ代入は、オブジェクトを有効な(ただし通常は不特定な)状態に置くことが保証されています。
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) |
ムーブコンストラクタが例外を投げない場合に引数をxvalueに変換する (関数テンプレート) |
| (C++11) |
要素の範囲を新しい場所にムーブする (関数テンプレート) |