SlideShare a Scribd company logo
unique_ptrにポインタ以外のもの
を持たせるとき
okada(@okdshin)
unique_ptrって?
C++11で登場したスマートポインタ
auto_ptrの完全上位互換
スコープを抜けたら自動で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も!)
デリータも設定できる
unique_ptrにデリータを設定
// Widgetのファクトリ関数
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
※デリータを設定する場合はmake_uniqueは使えない
unique_ptrからshared_ptrに変換
int main() {
// デリータごとunique_ptrをshared_ptrに変換可能
{
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は簡単にできるが逆はできない
∴ファクトリ関数の返り値型は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の代わりに開放関数を呼ぶ
};
// コンパイルエラー!! GetHandle()の返り値はポインタじゃないよ!!!
return std::unique_ptr<int, decltype(deleter)>(
others::GetHandle(), std::move(deleter));
}
int main() { auto h = make_unique_handle(); }
単に置き換えただけではコンパイルできない
デリータの中でpointer型を指定
namespace others {/*略*/}
// 昔ながらの関数オブジェクトクラス
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(); }
※ラムダではメンバ型が宣言できないため
関数オブジェクトクラスを使う
やったか……?
やってない
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);
^
もしハンドルが組み込み型じゃなくて、ユーザ定義型
だったらできるけど、そもそもなんでハンドルを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;
}
め、めんどくせえーッ!!!
例外安全性は?
ムーブはちゃんと実装できてる?
リソース漏れ本当にしない?
どのハンドルに対しても実装はほとんど同じなのにハ
ンドルごとに毎回書くの?
任意の型のリソースハンドルに
スコープを抜けたら自動で指定し
たデリータを実行してくれて
ムーブできて
標準ライブラリ並に信頼できる
RAIIラッパがほしい!!!!
あります。
N4189 Generic Scope Guard RAII
Wrapper for the Standard Library
unique_resource
unique_reource
C++標準化委員会のペーパーで次期標準ライブラリに加
えることを提案されているライブラリ
unique_ptrの一般化
unique_resourceによる実装
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(); // 明示的にハンドルをリリース
}
至極簡単に実装できる
「で? unique_resourceは
いつ使えるようになるの?」
「N4189にExample実装があるから
コピペしたら今すぐ使えるよ」
N4189のunique_resourceは
C++14対応コンパイラで使える
C++11でも少し修正すれば使える
まとめ
unique_ptrはデリータをカスタマイズできるが、ポイ
ンタ型のハンドルしか持てない
非ポインタ型ハンドルの自動リソース管理のために
unique_resourceが提案されている
N4189にunique_resourceの実装例があり、コピペした
ら使える
おまけ
std::threadのRAIIラッパ
Effective Modern C++ Item37
std::threadはjoinableの状態でデストラクタが呼ばれると
プログラムを終了させてしまう
int main() {
// tが処理を終える前にデストラクタが呼ばれると実行時エラーが起こる
std::thread t{[](){ std::cout << "hello" << std::endl; }};
}
そのためstd::threadはどのような実行経路でもデストラ
クタが呼ばれる前に非joinable状態にする必要がある
すなわちデストラクタを呼ぶ前にjoinかdetachする
まさにリソース管理の問題
EMC++ Item37における解決法
自分でRAIIクラスを書く
class unique_thread { // EMC++ではThreadRAII
public:
// デストラクト時の動作を指定できる
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を使った実装
デリータとしてラムダを渡すだけで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

PDF
C++ マルチスレッド 入門
京大 マイコンクラブ
 
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
 
PDF
Constexpr 中3女子テクニック
Genya Murakami
 
PDF
クロージャデザインパターン
Moriharu Ohzu
 
PDF
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
 
PDF
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
Ryo Sakamoto
 
PDF
すごい constexpr たのしくレイトレ!
Genya Murakami
 
PPTX
Effective Modern C++ 勉強会 Item 22
Keisuke Fukuda
 
C++ マルチスレッド 入門
京大 マイコンクラブ
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
 
Constexpr 中3女子テクニック
Genya Murakami
 
クロージャデザインパターン
Moriharu Ohzu
 
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
 
GPUが100倍速いという神話をぶち殺せたらいいな ver.2013
Ryo Sakamoto
 
すごい constexpr たのしくレイトレ!
Genya Murakami
 
Effective Modern C++ 勉強会 Item 22
Keisuke Fukuda
 

What's hot (20)

PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
 
PDF
マルチコアを用いた画像処理
Norishige Fukushima
 
PDF
LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例
National Cheng Kung University
 
PPTX
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
Fixstars Corporation
 
PDF
競技プログラミングにおけるコードの書き方とその利便性
Hibiki Yamashiro
 
PDF
C++ マルチスレッドプログラミング
Kohsuke Yuasa
 
PDF
カスタムメモリマネージャと高速なメモリアロケータについて
alwei
 
PDF
What Can Compilers Do for Us?
National Cheng Kung University
 
PDF
インタフェース完全に理解した
torisoup
 
PDF
不遇の標準ライブラリ - valarray
Ryosuke839
 
PDF
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Hiro H.
 
PDF
中3女子でもわかる constexpr
Genya Murakami
 
PDF
闇魔術を触ってみた
Satoshi Sato
 
PDF
Ml system in_python
yusuke shibui
 
PDF
Unreal Open Day 2017_Unreal Engine 4 Animation
Epic Games China
 
PPTX
競技プログラミングのためのC++入門
natrium11321
 
PDF
ゲーム開発者のための C++11/C++14
Ryo Suzuki
 
PDF
中3女子が狂える本当に気持ちのいい constexpr
Genya Murakami
 
PDF
2015年度先端GPGPUシミュレーション工学特論 第4回 GPUのメモリ階層の詳細 (共有メモリ)
智啓 出川
 
PDF
TRICK 2022 Results
mametter
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
Yoshifumi Kawai
 
マルチコアを用いた画像処理
Norishige Fukushima
 
LLVM 總是打開你的心:從電玩模擬器看編譯器應用實例
National Cheng Kung University
 
CPU / GPU高速化セミナー!性能モデルの理論と実践:理論編
Fixstars Corporation
 
競技プログラミングにおけるコードの書き方とその利便性
Hibiki Yamashiro
 
C++ マルチスレッドプログラミング
Kohsuke Yuasa
 
カスタムメモリマネージャと高速なメモリアロケータについて
alwei
 
What Can Compilers Do for Us?
National Cheng Kung University
 
インタフェース完全に理解した
torisoup
 
不遇の標準ライブラリ - valarray
Ryosuke839
 
Boost.勉強会 #21 札幌「C++1zにstring_viewが導入されてうれしいので紹介します」
Hiro H.
 
中3女子でもわかる constexpr
Genya Murakami
 
闇魔術を触ってみた
Satoshi Sato
 
Ml system in_python
yusuke shibui
 
Unreal Open Day 2017_Unreal Engine 4 Animation
Epic Games China
 
競技プログラミングのためのC++入門
natrium11321
 
ゲーム開発者のための C++11/C++14
Ryo Suzuki
 
中3女子が狂える本当に気持ちのいい constexpr
Genya Murakami
 
2015年度先端GPGPUシミュレーション工学特論 第4回 GPUのメモリ階層の詳細 (共有メモリ)
智啓 出川
 
TRICK 2022 Results
mametter
 
Ad

Similar to unique_ptrにポインタ以外のものを持たせるとき (19)

PPTX
Visual C++で使えるC++11
nekko1119
 
PPT
C++0x in programming competition
yak1ex
 
PDF
C++0x in programming competition
yak1ex
 
KEY
CUDAを利用したPIV解析の高速化
翔新 史
 
PPT
shared_ptr & weak_ptr (ppt 第2版, DL 専用)
Cryolite
 
PPT
shared_ptr & weak_ptr (ppt 初版, DL 専用)
Cryolite
 
PDF
Replace Output Iterator and Extend Range JP
Akira Takahashi
 
KEY
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
Yasuhiro Ishii
 
PDF
Emcpp item31
mitsutaka_takeda
 
PDF
TensorFlow Lite Delegateとは?
Mr. Vengineer
 
PDF
わんくま同盟大阪勉強会#61
TATSUYA HAYAMIZU
 
PPTX
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
Satoshi Mimura
 
PDF
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Takefumi MIYOSHI
 
PDF
#5:プログラミングの基本
長岡技術科学大学 自然言語処理研究室
 
PDF
Emcjp item21
MITSUNARI Shigeo
 
PDF
Boost.Flyweight
gintenlabo
 
PDF
PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)
CL0CL
 
PPT
プログラミングで言いたいこと聞きたいこと集
tecopark
 
PPT
プログラミングで言いたい聞きたいこと集
tecopark
 
Visual C++で使えるC++11
nekko1119
 
C++0x in programming competition
yak1ex
 
C++0x in programming competition
yak1ex
 
CUDAを利用したPIV解析の高速化
翔新 史
 
shared_ptr & weak_ptr (ppt 第2版, DL 専用)
Cryolite
 
shared_ptr & weak_ptr (ppt 初版, DL 専用)
Cryolite
 
Replace Output Iterator and Extend Range JP
Akira Takahashi
 
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
Yasuhiro Ishii
 
Emcpp item31
mitsutaka_takeda
 
TensorFlow Lite Delegateとは?
Mr. Vengineer
 
わんくま同盟大阪勉強会#61
TATSUYA HAYAMIZU
 
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
Satoshi Mimura
 
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Takefumi MIYOSHI
 
#5:プログラミングの基本
長岡技術科学大学 自然言語処理研究室
 
Emcjp item21
MITSUNARI Shigeo
 
Boost.Flyweight
gintenlabo
 
PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)
CL0CL
 
プログラミングで言いたいこと聞きたいこと集
tecopark
 
プログラミングで言いたい聞きたいこと集
tecopark
 
Ad

unique_ptrにポインタ以外のものを持たせるとき