58
グリとブランの C++ 講座 株式会社ヘキサドライブ 原 龍 (ドラゴン) C++98 (STL) と、ほんのちょっとの C++11 ~

グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Embed Size (px)

DESCRIPTION

C++入門者向けに、STLのコンテナを中心に解説してあります。

Citation preview

Page 1: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

グリとブランの C++ 講座

株式会社ヘキサドライブ

原 龍 (ドラゴン)

~ C++98 (STL) と、ほんのちょっとの C++11 ~

Page 2: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

最近はUnity等を使っての開発が浸透してきて、C++ を書く機会が少なくなってる気がするニョ。

名前:グリ 名前:ブラン

Page 3: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

確かにそうだけど、実行速度を求められるゲームプログラムは

まだまだ C++ で書くことも多いニャ。

Page 4: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

時代がソーシャル要素を盛り込んだネットワークゲームに移行しても、クライアントサイドはもちろんのこと、

サーバーサイドも C/C++ が最も使われてるんだニャ。

Page 5: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

へー、それはなんでかニョ?

Page 6: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

もちろん C++ じゃなくて GC が使える Java やC#、動的言語の Ruby や Python で書いたほうが

開発効率は格段に上がるニャ。

Page 7: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

でも C++ と Java/C# だったらスループット性能で10倍(※) 、C++ と Ruby/Python だったら

1000倍も違うと言われているんだニャ。

※JITコンパイラを備えるJavaVMでは、Cよりも速くなることがあるようです。ただし、ネットワークに対する入出力が多いゲームでは、システムコールを呼び出す前後でのバッファオーバーフローのチェック等が毎回生じるため、Cとの速度差が生まれるとのこと。

Page 8: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

おー、結構違うんだニョ。

Page 9: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

それだけ違ったら、用意するサーバーの台数も変わってくるニャ。

サーバーの運用コストって高いから…。

Page 10: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

確かに、できるだけお金はかけたくないニョ。

Page 11: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

そうだニャ。だから C++ について見てみるニャ。

Page 12: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

• 簡単に C++ の歴史と機能紹介

• Standard Template Library (STL)

• 【C++】サンプル【書いてみた】

Page 13: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

それじゃあ、さくっと C++ の歴史と機能を紹介するニャ。

Page 14: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

As for C++C++は、汎用プログラミング言語の一つである。

C言語の拡張として開発された。拡張はクラスの追加に始まり、仮想関数、多重定義、多重継承、テンプレート、例外処理といった機能が続いていった。

静的な型システムを持ち、手続き型プログラミング・データ抽象・オブジェクト指向プログラミング・ジェネリックプログラミングといった複数のプログラミングパラダイムをサポートするマルチパラダイムプログラミング言語である。

詳しくは wiki を見てね!http://ja.wikipedia.org/wiki/C%2B%2B

Page 15: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

C++98

• 初めての標準化

• STL に代表される標準ライブラリの追加

C++03• C++ 98での不具合の修正等

C++11

• C++98以来初の大きな改訂

• マルチスレッドやジェネリックプログラミングを強化

詳しくは wiki を見てね!http://ja.wikipedia.org/wiki/C%2B%2B

Page 16: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

クラス - Class

class Hoge {public: // どこからでもアクセス可能

Hoge(void) : _member(0) {} // コンストラクタvirtual ~Hoge(void) {} // デストラクタ

protected: // 継承した子クラスからのみアクセス可能void Function(void);

private: //クラス内からのみアクセス可能int _member;

};

オブジェクトの設計図。クラスから生成したオブジェクトをインスタンスという。クラスにはインスタンス生成時に呼ばれるコンストラクタと、インスタンスが破棄される時に呼ばれるデストラクタを定義できる。また、クラス内の関数(メンバ関数)や変数(メンバ変数) のアクセスレベルも指定できる。

Hoge* hoge = new Hoge();

Page 17: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

クラス - Class

class Parent {public:

Parent(void) : _member(0) {} virtual ~Parent(void) {}

protected: int _member;

};

class Child: public Parent {public:

Child(void) {}virtual ~Child(void) {}

void OutputMember(void) { std::cout << _member << std::endl; }};

クラスを継承することで、親クラスの機能を持ち合わせたまま、子クラスで拡張することもできる。

Page 18: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

オーバーライド - Override

class Parent {public:

void Function(void) { std::cout << "parent" << std::endl; }};

class Child : public Parent {public:

void Function(void) { std::cout << "child" << std::endl; }};

子クラスが親クラスのメンバ関数を上書きできる。

Parent* parent = new Child();Child* child = new Child();

parent->Function(); // parentchild->Function(); // child

Page 19: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

仮想関数 - Virtual Function

class Parent {public:

virtual void Function(void) { std::cout << "parent" << std::endl; }};

class Child : public Parent { public:

void Function(void) { std::cout << "child" << std::endl; }};

メンバ関数をオーバーライドした子クラスを、親クラスの型へアップキャストしながら格納した時に、メンバ関数の動作を上書きすることができる。

Parent* parent = new Child();Child* child = new Child();

parent->Function(); // childchild->Function(); // child

Page 20: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

Tips: デストラクタの落とし穴

class Parent {public:

Parent() { std::cout << "Parent Constructor" << std::endl; }~Parent() { std::cout << "Parent Destructor" << std::endl; }

};

class Child : public Parent {public:

Child() { std::cout << "Child Constructor" << std::endl; }~Child() { std::cout << "Child Destructor" << std::endl; }

};

継承される可能性のあるクラスのデストラクタは仮想関数にすること。仮想関数にしないと、ポリモーフィズムを活用した際に想定外の挙動となることがある。以下サンプル。

Page 21: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

Tips: デストラクタの落とし穴

Child child;/*

▼出力(特に問題なし)Parent ConstructorChild ConstructorChild DestructorParent Destructor

*/

Parent* pParent = new Child(); // 親の型にアップキャストdelete(pParent);/*

▼出力(宣言された型が優先されるため、子のデストラクタが呼ばれない!)Parent ConstructorChild ConstructorParent Destructor

*/

Page 22: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

純粋仮想関数 - Pure Virtual Function

class Parent {public:

virtual void Function(void) = 0; };

class Child : public Parent { public:

void Function(void) { std::cout << "child" << std::endl; }};

実装が無い、宣言のみの仮想関数。継承して実装をしなければインスタンス化できない。

//Parent* pParent= new Parent(); コンパイルエラー!Parent* pParent= new Child();pParent->Function(); // child

Page 23: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

多重定義 - Overload

class Hoge {public:

void Function(int n) { std::cout << n << std::endl; }void Function(float f) { std::cout << f << std::endl; }

};

引数を変えた、同名の関数や演算子を複数定義できる。

Hoge hoge;hoge.Function(1); hoge.Function(5.8f);

Page 24: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

テンプレート - Template

template <typename T>class Hoge {public:

void Function(T value) {std::cout << value << std::endl;

}};

コンパイル時にコードを生成できる。ジェネリックプログラミング(データ形式に依存しないプログラミング形式) に用いられる。コンパイル時に生成されるため、使用を誤るとコード量自体は多くないのに生成された実行ファイルのサイズが肥大化してしまうという危険性もあるため注意が必要。

Hoge<int> hoge1;hoge1.Function(1);

Hoge<float> hoge2;hoge2.Function(0.3f);

Page 25: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

簡単に C++ の歴史と機能紹介

テンプレートメタプログラミング- Template Metaprogramming

template <int N>struct Factorial{

enum { value = N * Factorial<N - 1>:: value};};

template <>struct Factorial<0> {

enum { value = 1 }; };

テンプレートを応用して再帰的にコードを生成することにより、動的な計算量を削減することができる。

// これらは実行時に計算することがないため、処理コストが少ない。int x = Factorial<4>::value; // 24int y = Factorial<0>::value; // 1

Page 26: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

代表的なものはこれくらいかニャ。

Page 27: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

あとは多重継承もあるけど、使ったら往々にしてコードが複雑化してしまうから、割愛するニャ。できるだけ単一継承と包含で対応するニャ。

※多重継承を使うことでコードが複雑化するというのは、あくまでも私見です。使い所を誤らなければ問題ありません。

Page 28: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

C++ 自体が機能的に多いという事はなくて、これらの機能を応用することで様々な案件に対応する

言語なんだニャ。テンプレートとかは奥が深いニャ。

Page 29: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~
Page 30: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

聞いてるのかニャ?

聞いてますニョ~

Page 31: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

じゃあ次は C++98 で標準化された、Standard Template Library (STL)

について解説するニャ。

Page 32: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

As for STL

テンプレートを最大限に生かす構成を取っており、コンテナ・イテレータ(反復子)・アルゴリズム・関数オブジェクトと呼ばれる各要素から成っている。

C++におけるジェネリックプログラミングのはしりとなった。

オブジェクトを格納するコンテナとそれを操作するアルゴリズム、その接点としてイテレータが存在し、コンテナとアルゴリズムが互いに完全に独立しているのも特徴の一つである。

詳しくは wiki を見てね!http://ja.wikipedia.org/wiki/Standard_Template_Library

Page 33: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

コンテナ:vector連続要素を保持する動的配列。STLの中では一番シンプルで有用な場面も多い。リファレンスは http://www.cppll.jp/cppreference/cppvector.html を参照。

特徴的なのは、格納された要素がメモリ空間において隣接しているということ。つまり、 &v[n] == &v[0] + n ということになる。そのため、末尾への要素追加における計算量は定数時間 O(1) となる。ちなみに中間への要素追加における計算量は線形時間 O(n) である。

vector はメモリの再割り当てを、それが必要になったタイミングで行う。(末尾への要素追加時に領域が確保できていなかったら、一定の領域を確保するなど)再割り当てを行う場合は一定のコストがかかるが、reserve を使用することにより、再割り当ての機会を減らすことも可能。API 呼び出しによるオーバーヘッドはあるが、malloc や new[] よりもメモリリークの回避や配列アクセスにイテレータを使用できたりと利点が多いため、vector は多くの場面で活用できる。

Page 34: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

コンテナ:deque (Double Ended Queue)双方向キュー。簡単に言うと、vector を末尾への追加だけではなく、双方向に追加できるようにしたもの。リファレンスは http://www.cppll.jp/cppreference/cppdeque.html を参照。

vector と同じく、先頭や末尾への要素追加は O(1) 、中間への要素追加は O(n)。内部的にはリングバッファというデータ構造になっており、確保した領域の先頭アドレスに要素がある状態で push_front した場合は、確保した領域の末尾に追加されるというイメージ。先頭要素の位置は保持しているため、push_front したからといって全ての要素がメモリ空間上で再配置されることはない。

先頭への要素追加/削除が行える点で vector よりも使い勝手が良いが 、reserve ができない、要素がメモリ空間上で連続しているという保証はないという欠点もあるため、どちらを採用するかは処理によって検討する必要がある。

Page 35: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

コンテナ:list双方向連結リスト。リファレンスは http://www.cppll.jp/cppreference/cpplist.html を参照。

vector や deque と違い、任意の位置への要素追加にかかる計算量が定数時間 O(1) となる。しかし、連結リストでデータを保持するため、ランダムアクセスは遅い。(先頭、末尾からの探索となる)また、必要な分しかメモリを確保しないという特徴もある。

メモリキャッシュに乗らないので、deque を使ったほうがパフォーマンス的に上がる事が多いかもしれない。

Page 36: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

コンテナ:set要素の重複を許さない集合。リファレンスは http://www.cppll.jp/cppreference/cppset.html を参照。要素の追加、検索、削除の計算量は対数時間 O(log n) となる。

vector と比べて重複を許さないというアルゴリズム的な差異があって使い勝手が良いが、一般的に Red-Black ツリー(http://ja.wikipedia.org/wiki/%E8%B5%A4%E9%BB%92%E6%9C%A8)によって実装されており、それによりツリーを構築するために相当なオーバーヘッドがかかってしまう。そのため、メモリキャッシュに乗ることも念頭に入れて、vector で重複チェックを行った上で要素を追加する方がパフォーマンス的には優れているとも言える。

Page 37: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

コンテナ:map連想コンテナ。キーと値を関連付けて管理する。リファレンスは http://www.cppll.jp/cppreference/cppmap.html を参照。set と同じで Red-Black ツリーなので、要素の追加、検索、削除の計算量は対数時間 O(log n) となる。使用する際のデメリットも set と同様。しかし、キーを指定の型に設定できることはメリットとして大きいため、使用したい場面も多い。

Page 38: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

コンテナアダプタ:stack 末尾からの挿入と末尾からの取り出しをサポート。Last In First Out (LIFO) とも呼ばれる。リファレンスは http://www.cppll.jp/cppreference/cppstack.html を参照。

コンテナアダプタ:queue 末尾からの挿入と先頭からの取り出しをサポート。First In First Out (FIFO) とも呼ばれる。リファレンスは http://www.cppll.jp/cppreference/cppqueue.html を参照。

※コンテナアダプタとはコンテナを内部に保持して、限定的に機能を公開しているもの。単体では使いにくいが、protected 継承することにより、内部のコンテナにアクセスできる。それにより独自の拡張が可能となっている。

Page 39: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

イテレータ - Iteratorイテレータはポインタと同じような使い方でコンテナの各要素にアクセスするために用意される。イテレータの中にもいくつか種類があるが、代表的なものは以下のものである。

▼前方イテレータ - forward_iterator要素の読み書きが行える。ただし前方への移動しかできない。

▼双方向イテレータ - bidirectional_iterator双方向へ移動しながら要素の読み書きが行える。list や set、map はこれ。

▼ランダムアクセスイテレータ - random_iteratorランダムアクセスが可能な双方向イテレータ。vector や deque はこれ。

Page 40: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

アルゴリズム - Algorithmコンテナに対する汎用的な処理を集めたもの。非常に多くの関数が用意されているため、STLを使用する際の恩恵として大きい。カテゴリとして、四種類に分類される。

・検索・操作 (http://www.cppll.jp/cppreference/cpp_algo_find.html)・配列操作 (http://www.cppll.jp/cppreference/cpp_algo_manip.html)・ソート関連 (http://www.cppll.jp/cppreference/cpp_algo_sort.html)・その他 (http://www.cppll.jp/cppreference/cpp_algo_other.html)

Page 41: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

Standard Template Library (STL)

関数オブジェクト - Function Object関数呼び出し演算子をオーバーロードすることにより、オブジェクトでありながら関数のように呼び出せる。関数ポインタやポリモーフィズムの代わりになり得る。アルゴリズムの中には関数オブジェクトを引数で与えるものもあり、それによって更にアルゴリズムの汎用性を向上させている。また、C++11 から標準化されたラムダ式を使うことで、より簡潔に書ける。

Page 42: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

STL はとても便利だけど、使い所を誤ると実行速度の低下やリソースの無駄遣いに繋がるから

気を付けるニャ。

Page 43: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

また、コンテナに関する箇所は私見で書いているところもあるから、色々な人の意見を参考にしたり、

自分でも考えて使うようにしてほしいニャ。

Page 44: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

便利なものこそ、よく考えて使えってことだニョ。

Page 45: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

その通りだニャ。最後にいくつかサンプルを載せるニャ。

Page 46: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

公開するインターフェースクラスと実装部分を切り離す

// インターフェースクラス。公開する。class IModel {public:

IModel(void) {} virtual ~IModel(void) {}

virtual void SetPosition(const Vector3& position) = 0;virtual const Vector3& GetPosition(void) const= 0;

};

Page 47: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

公開するインターフェースクラスと実装部分を切り離す

// 実装部分。公開しない。class Model : public IModel { public:

Model(void) : _position() {}virtual ~Model(void) {}

void Update();void Draw();

void SetPosition(const Vector3& position) { this->_position = position; }const Vector3& GetPosition(void) const { return this->_position; }

private:Vector3 _position ;

};

Page 48: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

公開するインターフェースクラスと実装部分を切り離す

// モデル作成クラスclass ModelCreator { public:

static IModel* Create(void); // new Model(); };

// ポリモーフィズムIModel * pModel = ModelCreator::Create();

Page 49: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

typedef std::vector<int> IntList;IntList list; list.push_back(1000);

for (int i = 0; i < 10 ; ++i) {list.push_back(std::rand());

}

std::sort(list.begin(), list.end());IntList::iterator it = std::find(list.begin(), list.end(), 1000);list.erase(it, list.end());

リストにランダムな整数値を入力し、閾値を基準に削除する

Page 50: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

ポリシークラス - Policy Class

struct NoChecking {template <typename T>static bool CheckPointer(T*) { return true; }

};struct NullChecking {

template <typename T>static bool CheckPointer(T* p) { return (p != nullptr); }

};struct BadPointerDoNothing {

template <typename T>static T* HandleBadPointer(T* p) { std::cout << "pointer is moldy" << std::endl; return

p; }};

構文的に同じインタフェースの下で、異なる処理を提供する。ポリシーを使うクラスは、それが使うそれぞれのポリシーに対してひとつのテンプレート引数を持って、テンプレート化されている。 このため必要なポリシーを選択することが出来る。

Page 51: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

ポリシークラス - Policy Class

template <typename T,typename CheckingPolicy = NoChecking,typename BadPointerPolicy = BadPointerDoNothing>

class PointerWrapper {public:

PointerWrapper() : _value(nullptr) {}explicit PointerWrapper(T* p) : _value(p) {} // 暗黙的呼び出しを禁止

operator T*() {if (!CheckingPolicy::CheckPointer(_value)) {

return BadPointerPolicy::HandleBadPointer(_value);} else {

return _value;}

}private:

T* _value ; };

Page 52: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

ポリシークラス - Policy Class

PointerWrapper<int> num1(new int);*num1 = 42;std::cout << "num1:" << *num1 << std::endl;

// これは実行時にNULLアクセスによるエラーになる。//PointerWrapper<int> num2;//*num2 = 42;//std::cout << "num2:" << *num2 << std::endl;

// これもエラーになるが、NULLアクセス前に pointer is moldy と出力する。//PointerWrapper<int, NullChecking> num3;//*num3 = 42;//std::cout << "num3:" << *num3 << std::endl;

Page 53: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

おまけとして、機能紹介って意味でC++11 のサンプルコードを載せるニャ。

詳細な解説は、また別の機会にするニャ。

Page 54: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

型推論

// イテレータの型は複雑std::vector<int>::iterator it = vector.begin();↓// このような形で型判別をコンパイラ任せることで、可読性を上げ、冗長性を省くauto it = vector.begin();

// また、decltypeもひとつの選択肢として用意されている。int foo;decltype(foo) bar = 1; // fooと同じ型でコンパイル時に決定される

Page 55: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

NULLポインタ

void foo(char *);void foo(int);

foo(NULL); // foo(int) が呼ばれる!

定数 0 には整数定数と NULL ポインタという二つの側面がある。これまで NULL はプリプロセッサマクロで 0 となるように定義されてきた。しかし 0 はあらゆるポインタ型への変換が許されているため、オーバーロードの使い方によっては意図した動作をしないことがある。

そのため、新たな予約語として nullptr が用意された。nullptr は整数型との比較や代入は禁止されているが、NULL と同様にあらゆるポインタ型への変換が許されている。今後、NULL が非推奨となる可能性もあるので、nullptr を使うように心掛けたい。

Page 56: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

ラムダ式

// 関数オブジェクトと同じように使えるvoid* ptr = NULL;auto isNullptr = [](void* ptr) { return ptr == nullptr; }; if (isNullptr(ptr)) {

std::cout << "ptr is null." << std::endl;}

// その場で呼び出すこともできるint square2 = [](int x) { return x * x; } (2);std::cout << square2 << std::endl; // 4

// Hello,Worldをこんな書き方することも可能。特にこうする意味は無いけど。[]() { std::cout << "Hello,World" << std::endl; } ();

Page 57: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

【C++】サンプル【書いてみた】

ラムダ式を使ってクロージャ

int sum = 0;

std::vector<int> list;list.push_back(1);list.push_back(2); list.push_back(3);

std::for_each(list.begin(), list.end(), [&sum](int x) {sum += x; // このラムダ式が宣言されているスコープの変数にアクセス可能

});

std::cout << sum<< std::endl; // 6

Page 58: グリとブランのC++講座 ~c++98(stl)と、ほんのちょっとのc++11~

お疲れ様でした。それではまた次の機会に。