M.4 std::move
https://www.learncpp.com/cpp-tutorial/stdmove/
moveの意味をもっと頻繁に使うと
l-valueの場合moveの意味を適用できます
myswap関数は3回コピーされます
前回の授業で知ったように、copyは無効です.
そして例として、本swapは3回のcopyを使用する
これによりstring copyとdestructが多すぎてプログラムが遅くなります
しかし、copyはここでは必要ありません.私たちに必要なのはaとbの値を交換するだけです.そのため、私たちは3回移動するだけでこの目的を達成することができます.しかもこれはcopyを使うときよりも効率的です.
しかし、どのようにしてそれを実現しますか?ここの問題はすべてl-valueです
r-valuerefではなくl-valueなので、move constructorまたはmove付与を呼び出すことはできません.では、どうすればいいのでしょうか.
c++11にはstd::moveという標準ライブラリ関数があります.
static castを使用してパラメータをr-valuereferenceに変換します
したがってmoveの意味が呼び出されます
したがって、std::move関数を使用して、l-valueを使用することなくmove constructorを呼び出し、値を割り当てることができます.std::moveはユーティリティヘッダで定義されていることに注意してください.
これはstd::moveを使用する同じ例です.
copyを作成する前にmoveでより効率的なプログラムになります
std::moveを使用してstd::vectorのようなコンテナに対してl-valueを使用してmoveの意味を適用することができます.
次の例では、copyの意味とmoveの意味が同時に存在します.
多くのソートアルゴリズムはswapingを使用します
この場合std::moveのmove semanticsを使用するとより効果的です
また、スマートポインタで管理されているコンテンツを移動したい場合にも役立ちます.
std::moveはいつでもr-valueのようにl-valueを扱うことができる
これは通常move semanticsを呼び出すためです
moveの意味をもっと頻繁に使うと
l-valueの場合moveの意味を適用できます
#include <iostream>
#include <string>
template<class T>
void myswap(T& a, T& b)
{
T tmp { a }; // invokes copy constructor
a = b; // invokes copy assignment
b = tmp; // invokes copy assignment
}
int main()
{
std::string x{ "abc" };
std::string y{ "de" };
std::cout << "x: " << x << '\n';
std::cout << "y: " << y << '\n';
myswap(x, y);
std::cout << "x: " << x << '\n';
std::cout << "y: " << y << '\n';
return 0;
}
上記swapを行う場合myswap関数は3回コピーされます
前回の授業で知ったように、copyは無効です.
そして例として、本swapは3回のcopyを使用する
これによりstring copyとdestructが多すぎてプログラムが遅くなります
しかし、copyはここでは必要ありません.私たちに必要なのはaとbの値を交換するだけです.そのため、私たちは3回移動するだけでこの目的を達成することができます.しかもこれはcopyを使うときよりも効率的です.
しかし、どのようにしてそれを実現しますか?ここの問題はすべてl-valueです
r-valuerefではなくl-valueなので、move constructorまたはmove付与を呼び出すことはできません.では、どうすればいいのでしょうか.
std::move
c++11にはstd::moveという標準ライブラリ関数があります.
static castを使用してパラメータをr-valuereferenceに変換します
したがってmoveの意味が呼び出されます
したがって、std::move関数を使用して、l-valueを使用することなくmove constructorを呼び出し、値を割り当てることができます.std::moveはユーティリティヘッダで定義されていることに注意してください.
これはstd::moveを使用する同じ例です.
#include <iostream>
#include <string>
#include <utility> // for std::move
template<class T>
void myswap(T& a, T& b)
{
T tmp { std::move(a) }; // invokes move constructor
a = std::move(b); // invokes move assignment
b = std::move(tmp); // invokes move assignment
}
int main()
{
std::string x{ "abc" };
std::string y{ "de" };
std::cout << "x: " << x << '\n';
std::cout << "y: " << y << '\n';
myswap(x, y);
std::cout << "x: " << x << '\n';
std::cout << "y: " << y << '\n';
return 0;
}
前の例とは異なりmywapではmoveの意味が3回呼び出されていることがわかりますcopyを作成する前にmoveでより効率的なプログラムになります
Another example
std::moveを使用してstd::vectorのようなコンテナに対してl-valueを使用してmoveの意味を適用することができます.
次の例では、copyの意味とmoveの意味が同時に存在します.
#include <iostream>
#include <string>
#include <utility> // for std::move
#include <vector>
int main()
{
std::vector<std::string> v;
std::string str = "Knock";
std::cout << "Copying str\n";
v.push_back(str); // calls l-value version of push_back, which copies str into the array element
std::cout << "str: " << str << '\n';
std::cout << "vector: " << v[0] << '\n';
std::cout << "\nMoving str\n";
v.push_back(std::move(str)); // calls r-value version of push_back, which moves str into the array element
std::cout << "str: " << str << '\n';
std::cout << "vector:" << v[0] << ' ' << v[1] << '\n';
return 0;
}
Where else is std::move useful?
多くのソートアルゴリズムはswapingを使用します
この場合std::moveのmove semanticsを使用するとより効果的です
また、スマートポインタで管理されているコンテンツを移動したい場合にも役立ちます.
Conclusion
std::moveはいつでもr-valueのようにl-valueを扱うことができる
これは通常move semanticsを呼び出すためです
Reference
この問題について(M.4 std::move), 我々は、より多くの情報をここで見つけました https://velog.io/@ikmy0ung/M.4-stdmoveテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol