SlideShare a Scribd company logo
1 of 28
Download to read offline
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

What's hot

組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22Keisuke Fukuda
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するYoshifumi Kawai
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングKohsuke Yuasa
 
コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」Masahito Zembutsu
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会Akihiko Matuura
 
C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話Kinuko Yasuda
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ信之 岩永
 
MagicOnion入門
MagicOnion入門MagicOnion入門
MagicOnion入門torisoup
 
C#とILとネイティブと
C#とILとネイティブとC#とILとネイティブと
C#とILとネイティブと信之 岩永
 
カスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについてカスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについてalwei
 
【Unite Tokyo 2019】Understanding C# Struct All Things
【Unite Tokyo 2019】Understanding C# Struct All Things【Unite Tokyo 2019】Understanding C# Struct All Things
【Unite Tokyo 2019】Understanding C# Struct All ThingsUnityTechnologiesJapan002
 
The Usage and Patterns of MagicOnion
The Usage and Patterns of MagicOnionThe Usage and Patterns of MagicOnion
The Usage and Patterns of MagicOnionYoshifumi Kawai
 
BuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルドBuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルドAkihiro Suda
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!Genya Murakami
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門natrium11321
 
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計UnityTechnologiesJapan002
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロdigitalghost
 

What's hot (20)

組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
 
コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」コンテナの作り方「Dockerは裏方で何をしているのか?」
コンテナの作り方「Dockerは裏方で何をしているのか?」
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
 
C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話C++でCプリプロセッサを作ったり速くしたりしたお話
C++でCプリプロセッサを作ったり速くしたりしたお話
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
C++ マルチスレッド 入門
C++ マルチスレッド 入門C++ マルチスレッド 入門
C++ マルチスレッド 入門
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
MagicOnion入門
MagicOnion入門MagicOnion入門
MagicOnion入門
 
C#とILとネイティブと
C#とILとネイティブとC#とILとネイティブと
C#とILとネイティブと
 
カスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについてカスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについて
 
【Unite Tokyo 2019】Understanding C# Struct All Things
【Unite Tokyo 2019】Understanding C# Struct All Things【Unite Tokyo 2019】Understanding C# Struct All Things
【Unite Tokyo 2019】Understanding C# Struct All Things
 
The Usage and Patterns of MagicOnion
The Usage and Patterns of MagicOnionThe Usage and Patterns of MagicOnion
The Usage and Patterns of MagicOnion
 
BuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルドBuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルド
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
 
競技プログラミングのためのC++入門
競技プログラミングのためのC++入門競技プログラミングのためのC++入門
競技プログラミングのためのC++入門
 
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計
【Unite 2018 Tokyo】60fpsのその先へ!スマホの物量限界に挑んだSTG「アカとブルー」の開発設計
 
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
二分探索法で作る再帰呼び出しできるCプリプロセッサマクロ
 

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

Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11nekko1119
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competitionyak1ex
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competitionyak1ex
 
CUDAを利用したPIV解析の高速化
CUDAを利用したPIV解析の高速化CUDAを利用したPIV解析の高速化
CUDAを利用したPIV解析の高速化翔新 史
 
shared_ptr & weak_ptr (ppt 第2版, DL 専用)
shared_ptr & weak_ptr (ppt 第2版, DL 専用)shared_ptr & weak_ptr (ppt 第2版, DL 専用)
shared_ptr & weak_ptr (ppt 第2版, DL 専用)Cryolite
 
shared_ptr & weak_ptr (ppt 初版, DL 専用)
shared_ptr & weak_ptr (ppt 初版, DL 専用)shared_ptr & weak_ptr (ppt 初版, DL 専用)
shared_ptr & weak_ptr (ppt 初版, DL 専用)Cryolite
 
Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPReplace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPAkira Takahashi
 
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519Yasuhiro Ishii
 
TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?Mr. Vengineer
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61TATSUYA HAYAMIZU
 
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。Satoshi Mimura
 
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Takefumi MIYOSHI
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweightgintenlabo
 
PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)
PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)
PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)CL0CL
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターンMoriharu Ohzu
 
プログラミングで言いたい聞きたいこと集
プログラミングで言いたい聞きたいこと集プログラミングで言いたい聞きたいこと集
プログラミングで言いたい聞きたいこと集tecopark
 
プログラミングで言いたいこと聞きたいこと集
プログラミングで言いたいこと聞きたいこと集プログラミングで言いたいこと聞きたいこと集
プログラミングで言いたいこと聞きたいこと集tecopark
 

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

Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competition
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competition
 
CUDAを利用したPIV解析の高速化
CUDAを利用したPIV解析の高速化CUDAを利用したPIV解析の高速化
CUDAを利用したPIV解析の高速化
 
shared_ptr & weak_ptr (ppt 第2版, DL 専用)
shared_ptr & weak_ptr (ppt 第2版, DL 専用)shared_ptr & weak_ptr (ppt 第2版, DL 専用)
shared_ptr & weak_ptr (ppt 第2版, DL 専用)
 
shared_ptr & weak_ptr (ppt 初版, DL 専用)
shared_ptr & weak_ptr (ppt 初版, DL 専用)shared_ptr & weak_ptr (ppt 初版, DL 専用)
shared_ptr & weak_ptr (ppt 初版, DL 専用)
 
Replace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JPReplace Output Iterator and Extend Range JP
Replace Output Iterator and Extend Range JP
 
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
DE0でラジコンカー作ってみた 関西de0 fpga勉強会20120519
 
Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?TensorFlow Lite Delegateとは?
TensorFlow Lite Delegateとは?
 
わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61わんくま同盟大阪勉強会#61
わんくま同盟大阪勉強会#61
 
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
 
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512
 
#5:プログラミングの基本
#5:プログラミングの基本#5:プログラミングの基本
#5:プログラミングの基本
 
Emcjp item21
Emcjp item21Emcjp item21
Emcjp item21
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweight
 
PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)
PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)
PerlのOOPにおいて、コンストラクタ 内でメンバ関数を呼ぶ方法は?(Perl Beginners #15)
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
 
プログラミングで言いたい聞きたいこと集
プログラミングで言いたい聞きたいこと集プログラミングで言いたい聞きたいこと集
プログラミングで言いたい聞きたいこと集
 
プログラミングで言いたいこと聞きたいこと集
プログラミングで言いたいこと聞きたいこと集プログラミングで言いたいこと聞きたいこと集
プログラミングで言いたいこと聞きたいこと集
 

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