実戦c++のスマートポインタunique_ptrシリーズ--unique_ptrとlambdaのエラー結合(特にlambdaのunique_ptrをキャプチャ)
7796 ワード
Lambda式はC++11に新しく導入されたもので,コードが簡潔明瞭になるように多くの便利さをもたらした.
でもuniqueをptrとlambda式を結合すると、エラーが発生しやすく、致命的です.
次のコードを直接見てください.
しかし、残念なことに、このコードのコンパイルではエラーが発生しますが、ラッキーです.
簡単な分析lambda式では値による伝達を使用しています.値で渡すとコピーが生成され、uniqueが生成されます.ptrのcopy;しかし、私たちは知っています.これは明らかに間違いです.
解決策は簡単です.ポインタによる代わりにリファレンスによる伝達です.
上の内容は前菜にすぎませんが、lambda式でuniqueをキャプチャしたい場合はptr、どうなるの?
非常に優雅に次のコードを書きます.
すべてが完璧で、コンパイル運転出力が正しい.
次に、もう少し仕事をします.
おめでとうございます.コンパイルエラーです.
原因は何ですか.なぜauto str 2=std::move(capturedStr);間違いは?これがlambda式の知識です.lambda式のデフォルトはconstです.もちろんstd::moveはconstオブジェクトではありません.
解決方法も簡単です.キーワードmutableプログラムを追加すると、以下のように動作します.
でもuniqueをptrとlambda式を結合すると、エラーが発生しやすく、致命的です.
次のコードを直接見てください.
#include "stdafx.h"
#include
#include
#include
class Message {
public:
Message() {}
};
int main(int argc, char* argv[])
{
std::vector<std::unique_ptr >messages;
for (int i = 0; i < 1000; i++) {
std::unique_ptr testMess;
messages.push_back(std::move(testMess));
}
std::for_each(messages.begin(), messages.end(),
[](std::unique_ptr testMess) {
// do something stupid
});
return 0;
}
しかし、残念なことに、このコードのコンパイルではエラーが発生しますが、ラッキーです.
d:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm(24): error C2280: “std::unique_ptr,std::default_delete<_ty>>::unique_ptr(const std::unique_ptr<_ty>,std::default_delete<_ty>> &)”:
簡単な分析lambda式では値による伝達を使用しています.値で渡すとコピーが生成され、uniqueが生成されます.ptrのcopy;しかし、私たちは知っています.これは明らかに間違いです.
解決策は簡単です.ポインタによる代わりにリファレンスによる伝達です.
#include
#include
#include
#include
class Message {
public:
Message() {}
};
int main(int argc, char* argv[])
{
std::vector<std::unique_ptr >messages;
for (int i = 0; i < 1000; i++) {
std::unique_ptr testMess;
messages.push_back(std::move(testMess));
}
std::for_each(messages.begin(), messages.end(),
[](std::unique_ptr &testMess) {
// do something stupid
});
return 0;
}
上の内容は前菜にすぎませんが、lambda式でuniqueをキャプチャしたい場合はptr、どうなるの?
非常に優雅に次のコードを書きます.
#include
#include
#include
int main()
{
auto str = std::make_unique<std::string>("my string");
auto lambda = [capturedStr = std::move(str)]{
std::cout << *capturedStr.get() << std::endl;
};
lambda();
return 0;
}
すべてが完璧で、コンパイル運転出力が正しい.
次に、もう少し仕事をします.
#include
#include
#include
int main()
{
auto str = std::make_unique<std::string>("my string");
auto lambda = [capturedStr = std::move(str)] {
std::cout << *capturedStr.get() << std::endl;
auto str2 = std::move(capturedStr);
std::cout << *str2 << std::endl;
};
lambda();
return 0;
}
おめでとうございます.コンパイルエラーです.
原因は何ですか.なぜauto str 2=std::move(capturedStr);間違いは?これがlambda式の知識です.lambda式のデフォルトはconstです.もちろんstd::moveはconstオブジェクトではありません.
解決方法も簡単です.キーワードmutableプログラムを追加すると、以下のように動作します.
#include
#include
#include
int main()
{
auto str = std::make_unique<std::string>("my string");
auto lambda = [capturedStr = std::move(str)] ()mutable {
std::cout << *capturedStr.get() << std::endl;
auto str2 = std::move(capturedStr);
std::cout << *str2 << std::endl;
};
lambda();
return 0;
}