際際滷

際際滷Share a Scribd company logo
unique_ptrにポインタ參翌のもの
を隔たせるとき
okada(@okdshin)
unique_ptrって
C++11で鞠したスマ`トポインタ
auto_ptrの頼畠貧了札Q
スコ`プをiけたら徭咾delete
#include <iostream>
#include <memory> // for unique_ptr
class Widget {
public:
~Widget() { std::cout << "deleted" << std::endl; }
};
int main() {
std::unique_ptr<Widget> wp{new Widget{}};
}
//output:
// deleted
newだ。 △撮。。。
int main() {
//std::unique_ptr<Widget> wp{new Widget{}};
auto wp = std::make_unique<Widget>();
}
☆make_uniqueはC++14から鞠
unique_ptrは宴旋
リソ`スを徭咾秤_慧してくれる
紳覆皀妊侫ルトだとポインタと揖殻業でくない
STLコンテナの勣殆にできる┐發舛蹐vectorも。
デリ`タもO協できる
unique_ptrにデリ`タをO協
// Widgetのファクトリv方
decltype(auto) make_widget() {
auto deleter = [](Widget* wp) {
std::cout << "deleter is called" << std::endl;
delete wp;// きちんとdeleteしておく
};
return std::unique_ptr<Widget, decltype(deleter)>{
new Widget{}, std::move(deleter)};
}
int main() {
auto wp = make_widget();
}
//output:
// deleter is called
// deleted
☆デリ`タをO協する栽はmake_uniqueは聞えない
unique_ptrからshared_ptrにQ
int main() {
// デリ`タごとunique_ptrをshared_ptrにQ辛嬬
{
std::shared_ptr<Widget> shared_wp{make_widget()};
}
{
auto wp = make_widget();
std::shared_ptr<Widget> shared_wp{std::move(wp)};
}
}
デリ`タもきちんと哈き@がれる
unique_ptr ★ shared_ptrはgにできるが剃はできない
÷ファクトリv方の卦りミ佑shared_ptrではなく
unique_ptrにするのがgood
じゃあ、リソ`スハンドルが
ポインタじゃなくてもいいんじゃ
ないの
リソ`スハンドルがポインタじゃなかったら
namespace others /*麿繁のAPI*/ {
int GetHandle() {/*待*/} // リソ`スハンドルはint侏
void ReleaseHandle(int handle) {/*待*/}
}
decltype(auto) make_unique_handle() {
auto deleter = [](int handle) {
others::ReleaseHandle(handle); // deleteの旗わりに_慧v方を柵ぶ
};
// コンパイルエラ`。 GetHandle()の卦り、魯櫂ぅ鵐燭犬磴覆い茖。。
return std::unique_ptr<int, decltype(deleter)>(
others::GetHandle(), std::move(deleter));
}
int main() { auto h = make_unique_handle(); }
gに崔きQえただけではコンパイルできない
デリ`タの嶄でpointer侏を峺協
namespace others {/*待*/}
// 劣ながらのv方オブジェクトクラス
struct deleter {
using pointer = int; // デフォルトではint*になるのを、intと峺協
void operator()(int handle) { others::ReleaseHandle(handle); }
};
decltype(auto) make_unique_handle() {
return std::unique_ptr<int, deleter>(
others::GetHandle(), deleter{});
}
int main() { auto h = make_unique_handle(); }
☆ラムダではメンバ侏が傚冱できないため
v方オブジェクトクラスを聞う
やったか´´
やってない
error: invalid operands of types
'int' and 'std::nullptr_t' to binary 'operator!='
if (__ptr != nullptr)
^
intとnullptrの曳^ができずコンパイルエラ`に
どうしようもない
bool operator!=(int, std::nullptr_t)は傚冱できない
bool my::operator!=(int, std::nullptr_t)' must have an argument of
class or enumerated type
bool operator!=(int i, std::nullptr_t n);
^
もしハンドルがMみzみ侏じゃなくて、ユ`ザ協x侏
だったらできるけど、そもそもなんでハンドルをnullptr
なんかと曳^しなくちゃいけないの
しょうがないので徭蛍で侏をく
class unique_handle {
void safe_release() {
if(handle_ == others::NullHandle) { return; }
others::ReleaseHandle(handle_);
handle_ = others::NullHandle;
}
int handle_;
public:
unique_handle() : handle_(others::GetHandle()) {}
unique_handle(unique_handle&& rhs)
: handle_{others::NullHandle} {
std::swap(handle_, rhs.handle_);
}
decltype(auto) operator=(unique_handle&& rhs) {
safe_release(); std::swap(handle_, rhs.handle_);
return *this;
}
め、めんどくせえ`ッ。。
箭翌芦畠來は
ム`ブはちゃんとg廾できてる
リソ`ス息れ云輝にしない
どのハンドルにしてもg廾はほとんど揖じなのにハ
ンドルごとに飴くの
販吭の侏のリソ`スハンドルに
スコ`プをiけたら徭咾盃原┐
たデリ`タをg佩してくれて
ム`ブできて
淵薀ぅ屮薀Kに佚mできる
RAIIラッパがほしい。。。
あります。
N4189 Generic Scope Guard RAII
Wrapper for the Standard Library
unique_resource
unique_reource
C++併溜T氏のペ`パ`で肝豚淵薀ぅ屮薀蠅房
えることを戻宛されているライブラリ
unique_ptrの匯違晒
unique_resourceによるg廾
namespace others {/*待*/}
decltype(auto) make_unique_handle() {
return std::experimental::make_unique_resource(
others::GetHandle(), &others::ReleaseHandle);
}
int main() {
auto h1 = make_unique_handle();
auto h2 = make_unique_handle();
auto h3 = make_unique_handle();
h2 = std::move(h3); // move辛嬬 h2の圷?のハンドルはリリ`ス
auto h4 = make_unique_handle();
std::cout << h4.get() << std::endl; // 伏のハンドルにアクセス
h4.reset(); // 苧幣議にハンドルをリリ`ス
}
崛Ogにg廾できる
仝で unique_resourceは
いつ聞えるようになるの拭
仝N4189にExampleg廾があるから
コピペしたら書すぐ聞えるよ々
N4189のunique_resourceは
C++14鬋灰鵐僖ぅ蕕琶垢┐
C++11でも富し俐屎すれば聞える
まとめ
unique_ptrはデリ`タをカスタマイズできるが、ポイ
ンタ侏のハンドルしか隔てない
掲ポインタ侏ハンドルの徭咼螢秋`ス砿尖のために
unique_resourceが戻宛されている
N4189にunique_resourceのg廾箭があり、コピペした
ら聞える
おまけ
std::threadのRAIIラッパ
Effective Modern C++ Item37
std::threadはjoinableの彜Bでデストラクタが柵ばれると
プログラムをK阻させてしまう
int main() {
// tがI尖をKえる念にデストラクタが柵ばれるとg佩rエラ`が軟こる
std::thread t{[](){ std::cout << "hello" << std::endl; }};
}
そのためstd::threadはどのようなg佩U揃でもデストラ
クタが柵ばれる念に掲joinable彜Bにする駅勣がある
すなわちデストラクタを柵ぶ念にjoinかdetachする
まさにリソ`ス砿尖の}
EMC++ Item37における盾Q隈
徭蛍でRAIIクラスをく
class unique_thread { // EMC++ではThreadRAII
public:
// デストラクトrの嘛を峺協できる
enum class dtor_action { join, detach };
unique_thread(std::thread&& t, dtor_action a)
: action_{a}, thread_{std::move(t)} {}
~unique_thread() {
if(thread_.joinable()) {
if(action_ == dtor_action::join) {
thread_.join();
}
else {
thread_.detach();
}
}
unique_resourceを聞ったg廾
デリ`タとしてラムダを局すだけでOK
enum class unique_thread_dtor_action { join, detach };
template<typename Func>
decltype(auto)
make_unique_thread(Func&& func, unique_thread_dtor_action action) {
return std::experimental::make_unique_resource(
std::thread{std::forward<Func>(func)},
[action](auto& thread) {
if(thread.joinable()) {
if(action == unique_thread_dtor_action::join) {
thread.join();
}
else {
thread.detach();
}
}
});
歌深
N4189 Generic Scope Guard and RAII Wrapper for the
Standard Library (Peter Sommerlad & Andrew L.Sandoval
2014)
Effective Modern C++ (Scott Meyers 2015)

More Related Content

顎稼庄援顎艶喝沿岳姻にポインタ參翌のものを隔たせるとき