SlideShare una empresa de Scribd logo
1 de 15
Effective Modern C++勉強会
#22
2015/05/20
福田 圭祐
@keisukefukuda
http://bit.ly/1KjcGeb
Item 22
pImplイディオムを使うときは
特殊メンバ関数を実装ファイルに記述しよう
http://bit.ly/1KjcGeb
pImplイディオムとは (1)
pImplイディオムを使わない場合の問題点
#include “gadget.h”
class Widget {
public:
Widget();
…
private:
std::string name;
std::vector<double> data;
Gadget g1, g2, g3;
};
Widgetを使うクライアントコードは、
gadget.h, widget.h, vector, string
に依存
• includeするファイルが多いことによる
コンパイル時間増大
• gadget.h と widget.h が変更されるたびに
クライアントコードも再コンパイルされる
[widget.h]
http://bit.ly/1KjcGeb
pImplイディオム =
– C++98からよく知られたテクニック
– インターフェースと実装を分離することによりヘッダファイ
ルの依存関係を軽減
pImplイディオムとは (2)
class Widget {
public:
Widget();
~Widget();
…
private:
struct Impl;
struct Impl *pImpl;
};
[widget.h]
#include “widget.h”
#include “gadget.h”
#include <vector>
#include <string>
struct Widget::Impl {
std::string name;
std::vector<double> data;
Gadget g1, g2, g3;
};
Widget::Widget() : pImpl(new Impl) { }
Widget::~Widget() { delete pImpl; }
[widget.cpp]
http://bit.ly/1KjcGeb
C++11:スマートポインタの使用
C++98におけるpImplイディオム
= 生ポインタの使用
_人人人人人人_
> 前世紀的 <
 ̄Y^Y^Y^Y^Y ̄
→ スマートポインタを使おう
http://bit.ly/1KjcGeb
std::unique_ptr の使用
Implクラスを、
– Widgetクラスの内側で動的に確保して
– Widgetクラスと同時に破棄
するなら、std::unique_ptr がよい
class Widget {
public:
Widget();
…
private:
struct Impl;
std::unique_ptr<Impl> pImpl;
};
[widget.h]
…
struct Widget::Impl {
std::string name;
std::vector<double> data;
Gadget g1, g2, g3;
};
Widget::Widget()
: pImpl(std::make_unique<Impl>()) { }
// no destructor
[widget.cpp]
http://bit.ly/1KjcGeb
std::unique_ptr の問題点 (1)
クライアントコードがコンパイルできない!
#include “widget.h”
Widget w;
In file included from client.cpp:1:
In file included from ./widget.hpp:1:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2
incomplete type 'Widget::Impl'
static_assert(sizeof(_Tp) > 0, "default_delete can not delete incomplete type");
^~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2
'std::__1::default_delete<Widget::Impl>::operator()' requested here
__ptr_.second()(__tmp);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2
'std::__1::unique_ptr<Widget::Impl, std::__1::default_delete<Widget::Impl> >::reset' requested here
_LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
^
./widget.hpp:3:7: note: in instantiation of member function 'std::__1::unique_ptr<Widget::Impl, std::__1::default
class Widget {
^
./widget.hpp:8:10: note: forward declaration of 'Widget::Impl'
struct Impl;
^
1 error generated.
LLVM3.6-svn0
http://bit.ly/1KjcGeb
std::unique_ptr の問題点 (1)
え!?
– std::unique_ptrはincomplete type でも使えると言わ
れている [*]
– pImplイディオムこそ、std::unique_ptrを一番使いた
いところ
幸い、解決はそれほど難しくない
[*] http://howardhinnant.github.io/incomplete.html
http://bit.ly/1KjcGeb
std::unique_ptrで何が起こっているか?
エラーの原因:
1. unique_ptrを使ったので、Widgetのデストラクタを省略
した
2. コンパイラがdtorを自動生成、メンバ pImpl のdtorが自
動で呼ばれる
3. pImpl のdtorは、unique_ptrのdefault deleter
4. 生ポインタに対して delete が呼ばれるが、その前に
static_assert を使って、ポインタがincomplete type
で無いことをチェックしている
5. → エラー
http://bit.ly/1KjcGeb
解決法
widgetのdtorから、Implクラスが見えるようにすれば
良い
class Widget {
public:
Widget();
~Widget();
…
private:
struct Impl;
std::unique_ptr<Impl> pImpl;
};
[widget.h]
…
struct Widget::Impl {
std::string name;
std::vector<double> data;
Gadget g1, g2, g3;
};
Widget::Widget()
: pImpl(std::make_unique<Impl>()) { }
Widget::~Widget() { }
[widget.cpp]
http://bit.ly/1KjcGeb
解決法
widgetのdtorから、Implクラスが見えるようにすれば
良い
– =default も使える
class Widget {
public:
Widget();
~Widget();
…
private:
struct Impl;
std::unique_ptr<Impl> pImpl;
};
[widget.h]
…
struct Widget::Impl {
std::string name;
std::vector<double> data;
Gadget g1, g2, g3;
};
Widget::Widget()
: pImpl(std::make_unique<Impl>()) { }
Widget::~Widget() = default;
[widget.cpp]
http://bit.ly/1KjcGeb
move操作のサポート
std::unique_ptr を使っているので、Widgetクラスはmove
セマンティクスをサポートするのが自然
dtorを自分で宣言したので、move操作は自動生成されない
(Item17参照) → 自分で宣言しましょう
class Widget {
public:
Widget();
~Widget();
Widget(Widget&&rhs);
Widget& operator=(const Widget&& rhs)
…
private:
struct Impl;
std::unique_ptr<Impl> pImpl;
};
[widget.h]
…
Widget::Widget(Widget&& rhs) = default;
Widget& Widget(const Widget&& rhs) = default;
…
[widget.cpp]
※ヘッダ中に定義を書いてしまうと
前と同じエラーになるので注意
(move ctor中で例外が発生した場合に
dtorを呼ぶ必要があるため)http://bit.ly/1KjcGeb
コピー操作のサポート
Widgetクラスは、内部にvector, string, Gadgetを含んでいるので、
もしGadgetがコピー可能であれば、Widgetもコピー可能である
はずだが、
1. std::unique_ptr は move-only
2. 仮にcopyをサポートしたとしても shallow-copy しかされない
→ やりたいのは(普通は) deep-copy
→自分で書く必要がある
class Widget {
…
Widget(Widget& rhs);
Widget& operator=(const Widget& rhs)
…
private:
struct Impl;
std::unique_ptr<Impl> pImpl;
};
[widget.h]
…
// Copy ctor
Widget::Widget(Widget& rhs)
: pImpl(std:: make_unique<Impl>(*rhs.pImpl
// copy operator
Widget& Widget(const Widget& rhs) {
*pImpl = *rhs.pImpl;
return *this;
}
…
[widget.cpp]
http://bit.ly/1KjcGeb
std::shared_ptrの利用
std::unique_ptr の代わりに std::shared_ptr を使うと、このような
一連の問題は起こらず、全てうまくいく
(move ctor等も全て自動生成でうまくいく)
custom deleter をサポートするための実装方法の違いによる
unique_ptr ・・・ deleterの型がsmart pointerの型の一部
→より小さく速いコードを出力できる可能性があ
るが、コンパイラが特殊関数を自動生成するた
めにはcomplete typeでなければならない
shared_ptr ・・・ deleterの型がsmart pointerの型の一部でない
→実行時のオーバーヘッドがあるが、complete
typeである必要が無い
http://bit.ly/1KjcGeb
Things to remember
• Pimplイディオムは、コンパイル時の依存関係を減ら
し、ビルド時間を短縮することができる
• Pimplイディオムでunique_ptrを使うときは、特殊メ
ンバ関数をヘッダーで宣言し、実装ファイルで定義
しよう(内容はデフォルト関数で問題無いとしても)
• shared_ptrの場合はこのような考慮は不要
http://bit.ly/1KjcGeb

Más contenido relacionado

La actualidad más candente

Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
Genya Murakami
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
Genya Murakami
 
shared_ptrとゲームプログラミングでのメモリ管理
shared_ptrとゲームプログラミングでのメモリ管理shared_ptrとゲームプログラミングでのメモリ管理
shared_ptrとゲームプログラミングでのメモリ管理
DADA246
 

La actualidad más candente (20)

Unityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTipsUnityでパフォーマンスの良いUIを作る為のTips
Unityでパフォーマンスの良いUIを作る為のTips
 
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭するCEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料Effective Modern C++勉強会#4 Item 17, 18資料
Effective Modern C++勉強会#4 Item 17, 18資料
 
Constexpr 中3女子テクニック
Constexpr 中3女子テクニックConstexpr 中3女子テクニック
Constexpr 中3女子テクニック
 
async/await のしくみ
async/await のしくみasync/await のしくみ
async/await のしくみ
 
IL2CPPに関する軽い話
IL2CPPに関する軽い話IL2CPPに関する軽い話
IL2CPPに関する軽い話
 
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
Unityによるリアルタイム通信とMagicOnionによるC#大統一理論の実現
 
Observableで非同期処理
Observableで非同期処理Observableで非同期処理
Observableで非同期処理
 
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
【Unite Tokyo 2018】さては非同期だなオメー!async/await完全に理解しよう
 
すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!すごい constexpr たのしくレイトレ!
すごい constexpr たのしくレイトレ!
 
Gstreamer Basics
Gstreamer BasicsGstreamer Basics
Gstreamer Basics
 
【Unite Tokyo 2018】Audio機能の基礎と実装テクニック
【Unite Tokyo 2018】Audio機能の基礎と実装テクニック【Unite Tokyo 2018】Audio機能の基礎と実装テクニック
【Unite Tokyo 2018】Audio機能の基礎と実装テクニック
 
Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16Effective Modern C++ 勉強会#3 Item16
Effective Modern C++ 勉強会#3 Item16
 
UniTask入門
UniTask入門UniTask入門
UniTask入門
 
shared_ptrとゲームプログラミングでのメモリ管理
shared_ptrとゲームプログラミングでのメモリ管理shared_ptrとゲームプログラミングでのメモリ管理
shared_ptrとゲームプログラミングでのメモリ管理
 
Emcpp0506
Emcpp0506Emcpp0506
Emcpp0506
 
良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方
 
できる!並列・並行プログラミング
できる!並列・並行プログラミングできる!並列・並行プログラミング
できる!並列・並行プログラミング
 

Destacado

Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26
Akihiro Nishimura
 
カスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについてカスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについて
alwei
 

Destacado (20)

Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12
 
Effective modern-c++#9
Effective modern-c++#9Effective modern-c++#9
Effective modern-c++#9
 
emc++ chapter32
emc++ chapter32emc++ chapter32
emc++ chapter32
 
effective modern c++ chapeter36
effective modern c++ chapeter36effective modern c++ chapeter36
effective modern c++ chapeter36
 
Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27Effective Modern C++ 勉強会#7 Item 27
Effective Modern C++ 勉強会#7 Item 27
 
Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15Effective Modern C++ 勉強会#3 Item 15
Effective Modern C++ 勉強会#3 Item 15
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39
 
Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26Effective Modern C++ 勉強会 Item26
Effective Modern C++ 勉強会 Item26
 
Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)Effective Modern C++勉強会#2 Item 11(,12)
Effective Modern C++勉強会#2 Item 11(,12)
 
Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25Effective Modern C++ 勉強会#6 Item25
Effective Modern C++ 勉強会#6 Item25
 
Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38Effective Modern C++ 勉強会#8 Item38
Effective Modern C++ 勉強会#8 Item38
 
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
Effective Modern C++ Item 24: Distinguish universal references from rvalue re...
 
Effective modern c++ 8
Effective modern c++ 8Effective modern c++ 8
Effective modern c++ 8
 
Emcjp item33,34
Emcjp item33,34Emcjp item33,34
Emcjp item33,34
 
emcjp Item 42
emcjp Item 42emcjp Item 42
emcjp Item 42
 
Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
Emcpp item41
Emcpp item41Emcpp item41
Emcpp item41
 
Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35Effective Modern C++ 読書会 Item 35
Effective Modern C++ 読書会 Item 35
 
Effective modern c++ 5
Effective modern c++ 5Effective modern c++ 5
Effective modern c++ 5
 
カスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについてカスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについて
 

Similar a Effective Modern C++ 勉強会 Item 22

Sohu邮箱的python经验
Sohu邮箱的python经验Sohu邮箱的python经验
Sohu邮箱的python经验
Ryan Poy
 
20150425 DroidKaigi つかえるGradleプロジェクトの作り方
20150425 DroidKaigi つかえるGradleプロジェクトの作り方20150425 DroidKaigi つかえるGradleプロジェクトの作り方
20150425 DroidKaigi つかえるGradleプロジェクトの作り方
Makoto Yamazaki
 
[Cloud Native Days Tokyo 2022] たまにはオンプレもいいぞ? GKE と Armadillo IoT で実現する ハイフ...
[Cloud Native Days Tokyo 2022] たまにはオンプレもいいぞ? GKE と Armadillo IoT で実現する ハイフ...[Cloud Native Days Tokyo 2022] たまにはオンプレもいいぞ? GKE と Armadillo IoT で実現する ハイフ...
[Cloud Native Days Tokyo 2022] たまにはオンプレもいいぞ? GKE と Armadillo IoT で実現する ハイフ...
Ryo Sasaki
 
わんくまT78 mfcを始めようとしてみた
わんくまT78 mfcを始めようとしてみたわんくまT78 mfcを始めようとしてみた
わんくまT78 mfcを始めようとしてみた
伸男 伊藤
 

Similar a Effective Modern C++ 勉強会 Item 22 (20)

Swift2 の新機能 Protocol Extension
Swift2 の新機能 Protocol ExtensionSwift2 の新機能 Protocol Extension
Swift2 の新機能 Protocol Extension
 
Github基礎 | [FLEXER Project]
Github基礎 | [FLEXER Project]Github基礎 | [FLEXER Project]
Github基礎 | [FLEXER Project]
 
Dependency injection
Dependency injectionDependency injection
Dependency injection
 
osakapy 2014.05 LT
osakapy 2014.05 LTosakapy 2014.05 LT
osakapy 2014.05 LT
 
Android App Development with Gradle & Android Studio
Android App Development with Gradle & Android StudioAndroid App Development with Gradle & Android Studio
Android App Development with Gradle & Android Studio
 
Houdini 製品概要
Houdini 製品概要 Houdini 製品概要
Houdini 製品概要
 
Github入門2014
Github入門2014Github入門2014
Github入門2014
 
Sohu邮箱的python经验
Sohu邮箱的python经验Sohu邮箱的python经验
Sohu邮箱的python经验
 
続・モジュール / Introduction to C++ modules (part 2)
続・モジュール / Introduction to C++ modules (part 2)続・モジュール / Introduction to C++ modules (part 2)
続・モジュール / Introduction to C++ modules (part 2)
 
Kubernetes Meetup Tokyo #23 kubebuilder-v2
Kubernetes Meetup Tokyo #23 kubebuilder-v2Kubernetes Meetup Tokyo #23 kubebuilder-v2
Kubernetes Meetup Tokyo #23 kubebuilder-v2
 
Code ignitertalk 01
Code ignitertalk 01Code ignitertalk 01
Code ignitertalk 01
 
20150425 DroidKaigi つかえるGradleプロジェクトの作り方
20150425 DroidKaigi つかえるGradleプロジェクトの作り方20150425 DroidKaigi つかえるGradleプロジェクトの作り方
20150425 DroidKaigi つかえるGradleプロジェクトの作り方
 
Gitを使ってみませんか
Gitを使ってみませんかGitを使ってみませんか
Gitを使ってみませんか
 
Git超入門_座学編.pdf
Git超入門_座学編.pdfGit超入門_座学編.pdf
Git超入門_座学編.pdf
 
はじめてのCodeIgniter
はじめてのCodeIgniterはじめてのCodeIgniter
はじめてのCodeIgniter
 
[Cloud Native Days Tokyo 2022] たまにはオンプレもいいぞ? GKE と Armadillo IoT で実現する ハイフ...
[Cloud Native Days Tokyo 2022] たまにはオンプレもいいぞ? GKE と Armadillo IoT で実現する ハイフ...[Cloud Native Days Tokyo 2022] たまにはオンプレもいいぞ? GKE と Armadillo IoT で実現する ハイフ...
[Cloud Native Days Tokyo 2022] たまにはオンプレもいいぞ? GKE と Armadillo IoT で実現する ハイフ...
 
Cognos reportauthoring b4_movie
Cognos reportauthoring b4_movieCognos reportauthoring b4_movie
Cognos reportauthoring b4_movie
 
Koin紹介
Koin紹介Koin紹介
Koin紹介
 
わんくまT78 mfcを始めようとしてみた
わんくまT78 mfcを始めようとしてみたわんくまT78 mfcを始めようとしてみた
わんくまT78 mfcを始めようとしてみた
 
Git_GiHub講習会.pdf
Git_GiHub講習会.pdfGit_GiHub講習会.pdf
Git_GiHub講習会.pdf
 

Effective Modern C++ 勉強会 Item 22