SlideShare una empresa de Scribd logo
1 de 62
Descargar para leer sin conexión
C++ 言語講習会第 1 回資料

書いた人:@sunaemon0(回路屋 2 年)
1 コンストラクタ
前回最後に使ったコードを再掲します。
list 1 constructor0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# include <cstdio >
class hal_adc {
private :
unsigned int value ;
public :
unsigned int get_value () {
return this -> value;
}
void set_value ( unsigned int value) {
this -> value = value;
}
};
int main(int , char **) {
hal_adc adc0;
adc. set_value (3);
std :: printf ("%dn", adc. get_value ());
return 0;
}
さて、c のコードの関数内で、
1
2
3
4
5
6

struct a
{
int i;
};
struct a b;

みたいなことを書いたとします。

6 行目の意味は、スタック領域に構造体 a 分の領域を確保す
るということです。
1
2
3
4
5
6

struct a
{
int i;
};
struct a b = {1};

と書けばこれは、スタック領域に構造体 a 分の領域を確保し
その中の i を 1 で初期化するという意味になります。
list 2 constructor1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# include <cstdio >
class hal_adc {
private :
unsigned int value ;
public :
hal_adc () {
printf (" constructor called n");
}
};
int main(int , char **) {
hal_adc adc0; // constructor called
return 0;
}

このプログラムを実行してみればわかりますが、14 行目が
実行されると、hal adc::hal adc が呼び出されます。
この呼び出される関数をコンストラクタと呼びます。
つまり、C++ で
1

hal_adc adc0;

と書けば、スタック領域に hal adc 分の領域を確保し、
hal adc のコンストラクタにこの領域を初期化させるという
意味になります。
2 デフォルトコンストラクタ
最初のコードでは、コンストラクタを定義しませんでした
が、コンパイルが通ります。これは、明示的にコンストラク
タを書かなかった場合、コンパイラがデフォルトコンストラ
クタを暗黙的に生成するためです。
デフォルトコンストラクタとは引数を持たないコンストラク
タ、または全ての引数にデフォルト引数が設定されているコ
ンストラクタのことを言います。
コンパイル生成のデフォルトコンストラクタはこの場合何も
しない関数になります。
この仕様によって C との上位互換性が保たれています。
コンストラクタは引数を持つことができます。この場合は記
法が少し変わります。
list 3 constructor2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# include <cstdio >
class hal_adc {
unsigned int value ;
public :
unsigned int get_value () {
return this -> value;
}
void set_value ( unsigned int value) {
this -> value = value;
}
hal_adc ( unsigned int value) {
this -> value = value;
}
hal_adc () {
this -> value = value;
}
};
int main(int , char **) {
hal_adc adc (3);
std :: printf ("%dn", adc. get_value ());
return 0;
}
ユーザー定義のコンストラクタがあるためデフォルトコンス
トラクタは生成されないことに注意してください。
list 4 constructor3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# include <cstdio >
class hal_adc {
unsigned int value ;
public :
unsigned int get_value () {
return this -> value;
}
void set_value ( unsigned int value) {
this -> value = value;
}
hal_adc ( unsigned int value) {
this -> value = value;
}
};
int main(int , char **) {
hal_adc adc; // no matching function for call to ‘ hal_adc :: hal_adc () ’
std :: printf ("%dn", adc. get_value ());
return 0;
}
C では以下のように定義と初期化を同時に行なっても、分け
て行なってもコストは変わりませんでした。
1

struct a b = {1};

1
2

struct a b;
b. value = 1;

しかし、C++ においては、一般的にはそうではありません。
定義と初期化を同時に行った場合、コンストラクタが一回呼
ばれるだけです。

c++ で後者のように書いた場合は、定義と初期化を行った後
に、更に代入を行うという意味になります。
またコンストラクタには以下のように初期化リストを指定で
きます。
基本的には、メンバ変数全てについて初期化子を指定し
ます。
list 5 constructor4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# include <cstdio >
struct data {
data () { std :: printf (" default constructor called n"); }
data(int) { std :: printf ("2nd constructor called n"); }
};
struct hal_adc {
data dat;
hal_adc (int d) : dat(d) {};
hal_adc () : dat () {};
};
int main(int , char **) {
hal_adc adc0;
// default constructor called
hal_adc adc1 (1); // 2nd constructor called
}
先ほどのように、初期化子を省略した場合、デフォルトコン
ストラクタが呼ばれます。もし初期化子を省略されたメンバ
変数が、デフォルトコンストラクタを持たない場合、コンパ
イルエラーが起きます。

const なメンバ変数及び参照は初期化子によって初期化され
なければそれ以降変更することは出来ません。
初期化子の呼ばれる順序は初期化リストの順序にではなく、
メンバの宣言された順番であることに気をつけてください。
混乱を避けるため、初期化リストの順序はメンバの宣言され
た順序にあわせてください。
list 6 constructor5.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# include <cstdio >
struct data {
data(int dat) { std :: printf ("%d ", dat); }
};
struct hal_adc {
data dat0;
data dat1;
hal_adc () : dat0 (1) , dat1 (2) {};
hal_adc (int a) : dat1 (2) , dat0 (1) {};
};
int main(int , char **) {
hal_adc adc0;
// 1 2
std :: printf ("n");
hal_adc adc1 (1);
// 1 2
std :: printf ("n");
return 0;
}

また、new 演算子でインスタンスを作る場合もコンストラク
タが呼ばれます。
別にコンストラクタを定義しない場合に、暗黙的にデフォル
トコンストラクタが作られてほしくないい場合、=delete を
後につけます。
list 7 constructor6.cpp
1
2
3
4
5
6
7
8
9
10
11

# include <cstdio >
struct hal_adc {
hal_adc () = delete ;
};
int main(int argc , char ** argv)
{
hal_adc adc0; // use of deleted function
return 0;
}

デフォルトコンストラクタを明示的に private で宣言すると
いう方法もありますが、こちらのほうが意図がわかりやすい
のでおすすめします。
別にコンストラクタを定義する場合に、デフォルトコンスト
ラクタをコンパイラ生成させたい場合、=defalut を後につけ
ます。
list 8 constructor7.cpp
1
2
3
4
5
6
7
8
9
10
11
12

# include <cstdio >
struct hal_adc {
hal_adc () = default ;
hal_adc (int a);
};
int main(int argc , char ** argv)
{
hal_adc adc0; // ok
return 0;
}

ここでは詳しく述べませんが、コンパイラが生成したデフォ
ルトコンストラクタと、それに等価な明示的に書いたデフォ
ルトコンストラクタは C++ の文法上扱いが異なるためこの
ような措置があります。
3 コピーコンストラクタ
引数として自分自身のインスタンスを取るコンストラクタの
ことをコピーコンストラクタと呼びます。
正確には、class T のコンストラクタであって、引数として
&T, const &T, volatile &T, volatile const &T 型の変数を取る
ものをいいます。
参照であることに注意してください。
コピーコンストラクタはその名の通りインスタンスをコピー
して新しいコンストラクタを作る必要があるときに呼び出さ
れます。
list 9 copyconstructor0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# include <cstdio >
struct hal_adc {
hal_adc () = default ;
hal_adc ( const hal_adc &) {
std :: printf ("copy constructor called n");
}
};
int main(int , char **)
{
hal_adc adc0;
hal_adc adc1 = adc0; // copy constructor called
return 0;
}
先ほどと同じようにユーザー定義のコピーコンストラクタを
定義しない場合、コンパイラはにコピーコンストラクタを生
成します。
仕様上インスタンスをコピー出来ないようにしたいクラスで
はコピーコンストラクタを削除することを忘れないようにし
てください。
引数を値渡しする場合にもコピーコンストラクタが呼ばれ
ます。
list 10 copyconstructor1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# include <cstdio >
struct hal_adc {
hal_adc () = default ;
hal_adc ( const hal_adc &) {
std :: printf ("copy constructor called n");
}
};
void f( const hal_adc &) { }
void g( hal_adc ) { }
int main(int , char **)
{
hal_adc adc;
f(adc); // no constructor called
g(adc); // constructor not called
return 0;
}
4 デストラクタ
スコープを外れたり、delete されたりしたインスタンスは、
そのデストラクタが呼ばれ解体されます。
list 11 destructor0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# include <cstdio >
struct hal_adc {
hal_adc () {
std :: printf (" default constructor called n");
}
hal_adc ( const hal_adc &) {
std :: printf ("copy constructor called n");
}
˜ hal_adc () {
std :: printf (" destructor called n");
}
};
int main(int , char **) {
hal_adc adc; // constructor called
return 0;
// destructor called
}
静的領域に確保されたインスタンスは、main 関数が呼ばれ
る前にコンストラクタで構築され、main を抜けた後にデス
トラクタによって解体されます。
デストラクタそのものはそんなに難しくはないのですが、例
外や継承と組み合わさると注意が必要になってきます。
5 RAII
コンストラクタで new を使って領域を確保し、デストラクタ
で delete で領域を開放することで delete 忘れを防止でき
ます。
このようにコンストラクタで資源を確保し、デストラクタで
それを開放するというパターンを Resource Acquisition is
Initialization(RAII) と言います。
例外安全なプログラムを書くにはこの概念が不可欠です。
list 12 vector0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# include <cstdio >
# include <vector >
class raii_test
{
char *buf;
public :
rail_test ( raii_test &x) = delete ;
operator =() = delete ;
raii_test (int size) {
this ->buf = new char[size ];
}
˜ rail_test () {
delete [] this ->buf;
}
}
int main(int , char **) {
raii_test a(10);

// new

std :: scanf ("%s", a);
std :: printf ("%s", a);
}

// delete
標準ライブラリでは、
std::vector,std::unique ptr,shd::shared ptr(メモリ資源を
RAII で管理) や std::fstream(ファイルポインタを RAII で管理)
や std::lock guard(セマフォと RAII で管理) などが例として
挙げられます。
6 const
list 13 hal0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# include <stdio .h>
struct hal_adc {
unsigned int value ;
};
void set_adc_value ( hal_adc *adc , unsigned int value ) {
adc -> value = value ;
}
unsigned int get_adc_value (const hal_adc *adc) {
return adc -> value ;
}
int main(int argc , char ** argv)
{
hal_adc adc;
set_adc_value (&adc , 3);
printf ("%dn", get_adc_value (& adc));
return 0;
}
list 14 hal1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# include <cstdio >
class hal_adc {
private :
unsigned int value ;
public :
unsigned int get_value () {
return this -> value;
}
void set_value ( unsigned int value) {
this -> value = value;
}
};
int main(int argc , char ** argv)
{
hal_adc adc;
adc. set_value (3);
std :: printf ("%dn", adc. get_value ());
return 0;
}

この2つを比較してみると、get adc value には const とい
うキーワードがあるのに対し、hal adc::get value には
const というキーワードがありません。
list 15 hal2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

# include <stdio .h>
struct hal_adc {
unsigned int value ;
};
void set_adc_value ( hal_adc *adc , unsigned int value ) {
adc -> value = value ;
}
unsigned int get_adc_value (const hal_adc *adc) {
return adc -> value ;
}
int main(int argc , char ** argv)
{
const hal_adc adc = {1};
printf ("%dn", get_adc_value (& adc));
return 0;
}

上のプログラムの 17 行目のようなことをするのには、下の
ように書く必要があります。
list 16 hal3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

# include <cstdio >
class hal_adc {
private :
unsigned int value ;
public :
hal_adc (int vlaue ) : value (vlaue ) { }
unsigned int get_value () const {
return this -> value;
}
void set_value ( unsigned int value) {
this -> value = value;
}
};
int main(int argc , char ** argv)
{
const hal_adc adc;
std :: printf ("%dn", adc. get_value ());
return 0;
}

このように関数名のあとに const を書くと this ポインタの中
身を変更できなくなります。
また、const のインスタンスの非 const なメンバ関数は呼べ
ません。
7 演算子オーバーロード
例えば次のような複素数を実装したクラスを考えてみます。
list 17 operator0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

class complex {
double re , im;
public :
complex ( double re , double im) {
this ->re = re;
this ->im = im;
}
complex add( complex &z) {
this ->re += z.re;
this ->im += z.im;
return *this;
}
};
int main(int , char **) {
complex x(1.0 , 2.1);
complex y(1.0 , 2.3);
x.add(y); // returns {2.0 , 4.4}
}
こういう実装もありえるでしょう。
list 18 operator1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

class complex {
double re , im;
public :
complex ( double
this ->re =
this ->im =
}
friend complex
};

re , double im) {
re;
im;
add( complex &x, complex &z);

complex add( complex &x, complex &y) {
return complex (x.re + y.re , x.im + y.im); // calles constructor
}
int main(int , char **) {
complex x(1.0 , 2.1);
complex y(1.0 , 2.3);
add(x,y);

// returns {2.0 , 4.4}

}

でも使い勝手が悪いです。
特に複数の数字を足すときに見た目が煩雑になります。
そこで、C++ では add(x,y) や x.add(y) の代わりに x+y とかけ
るようにする仕組みがあります。これを演算子オーバーロー
ドと言います。
具体的には以下のように書きます。
list 19 operator2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

class complex {
double re , im;
public :
complex ( double re , double im) {
this ->re = re;
this ->im = im;
}
complex operator +( complex &z) {
this ->re += z.re;
this ->im += z.im;
return *this;
}
};
int main(int , char **) {
complex x(1.0 , 2.1);
complex y(1.0 , 2.3);
x+y; // returns {2.0 , 4.4}
}
list 20 operator3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

class complex {
double re , im;
public :
complex ( double
this ->re =
this ->im =
}
friend complex
};

re , double im) {
re;
im;
operator +( complex &x, complex &z);

complex operator +( complex &x, complex &y) {
return complex (x.re + y.re , x.im + y.im); // calles constructor
}
int main(int , char **)
{
complex x(1.0 , 2.1);
complex y(1.0 , 2.3);
x+y; // returns {2.0 , 4.4}
}

C++ では演算子をオーバーロードすることはできますが、新
しい演算子を定義したり、結合性を変えたり、優先順位を変
えたりすることはできません。
C++ ではほとんどの単項演算子と、二項演算子がオーバー
ロードできます。オーバーロード出来ないのは三項演算子?:
とスコープ解決子::くらいです。
ただし、++,–,(),[],-> もオーバーロードできますが、後述の
通り、オーバーロード方法が少し他とは異なります。
普通の演算子については、もしクラス T で、ある単項演算子
@がオーバーロードされていれば、@ x というのは、
operator@(x) ないし、x.operator@() と等価になります。
また、もしクラス T で、ある単項演算子@がオーバーロード
されていれば、x @ y というのは、operator@(x, y) ないし、
x.operator@(y) と等価になります。
++ 及び–は前置・後置の区別があり、普通引数を変更するの
で扱いが少し異なりますがここでは省略します。
=,(),[],-> は非メンバ関数としてオーバーロードすることはで
きません。
operator=は、代入演算子とよばれます。他の演算子は継承
されるのに対し、代入演算子は継承されません。また引数の
型が T, T&, const T&, volatile T&, or const volatile T&のうち
どれかである者は特にコピー代入演算子と呼ばれます。
operator() は、他と違っていくつの引数でも取れます。
operator->() は特殊ですが細かいことは省略します。
8 代入演算子
代入演算子はすでに初期化されている変数にインスタンスを
代入した時に呼ばれます。
list 21 assignment0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# include <cstdio >
struct hal_adc {
hal_adc () {
std :: printf (" default constructor called n");
}
hal_adc ( const hal_adc &) {
std :: printf ("copy constructor called n");
}
hal_adc & operator =( const hal_adc &x) {
std :: printf ("copy assignment operator called n");
return *this;
}
};
int main(int , char **)
{
hal_adc adc0;

// calles default constructor
19
20
21
22

hal_adc adc1 = adc0; // calles copy constructor
adc0 = adc1;
// calles assignment operator
return 0;
}
9 iostream
operator¡¡のオーバーロードを乱用して、C++ ではこんなこ
とができるようになりました。オーバーロードによって %d
みたいに型を明示しなくても標準出力に吐き出せるようにな
りました。
list 22 iostream0.cpp
1
2
3
4
5
6
7
8
9
10

# include <string >
# include <iostream >
int main(int ,char **)
{
std :: string s;
std :: cin >> s;
std :: cout << s << std :: endl;
std :: cerr << "no error << std :: endl"
}
10 関数オブジェクト
operator() は先述したように引数の個数が特に決まっていま
せん。
list 23 function0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# include <iostream >
int succ0 (int i) { return i+1; }
struct succ1 {
int operator () (int i) { return i+1; }
};

int main(int , char **) {
int (*f0)(int) = succ0;
succ1 f1;
std :: cout << f0 (1) << std :: endl;
std :: cout << f1 (1) << std :: endl;
}
このように operator() を使うとまるでまるでそのクラスのイ
ンスタンスが関数のように振る舞います。
このように関数のように振る舞うオブジェクトを関数オブ
ジェクトといいます。
11 型推論
以下のように auto というキーワードを使うことで右辺から
自動的に型が推論され、変数定義を楽に書けるようになり
ます。
1
2
3
4

auto x = 5;
const auto *v = &x, u = 6;
static auto y = 0.0;
auto int r;

//
//
//
//

OK: x has type
OK: v has type
OK: y has type
error : auto is

int
const int*, u has type const int
double
not a storage -class - specifier

Working Draft, Standard for Programming Language C++(N3337) p149 より引用
12 テンプレート
本格的には次回以降やりますが、C++ にはテンプレートとい
う便利な奴があります。
マクロを型安全にしたものであると言えます。
list 24 template0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# include <iostream >
# include <string >
using namespace std;
# define add(T) T add_ ##T(T x, T y){ return x+y;}
add(int);
add( double );
add( string );
int main(int , char **) {
cout << add_int (1, 2) << endl;
// int version
cout << add_double (1.0 , 2.0) << endl; // double version
cout << add_string ("a", "b") << endl; // string version
}
list 25 template1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# include <iostream >
# include <string >
using namespace std;
template < class T> T add(T x, T y) {
return x+y;
}
template int add <int >(int ,int);
template double add <double >( double , double );
template double add <string >( string , string );
int main(int , char **) {
cout << add <int >(1 , 2) << endl;
// int version
cout << add <double >(1.0 , 2.0) << endl; // double version
cout << add <string >("a", "b") << endl; // string version
}
list 26 template2.cpp
1
2
3
4
5
6
7
8
9
10
11
12

# include <iostream >
# include <complex >
template < class T>
T add(T x, T y) {
return x+y;
}
int main(int , char **) {
std :: cout << add (1, 2) << std :: endl; // 版 int
std :: cout << add (1.0 , 2.0) << std :: endl; // 版 double
}
13 関数オブジェクトと関数ポインタ
C++ には、その後に () をつけて呼び出せるものが三種類あり
ます。

• 関数ポインタ
• 関数オブジェクト
• メンバ関数ポインタ (今回の講習会ではやらないかも)
関数ポインタと関数オブジェクトについてはどちらも () を付
けるだけで同じように呼び出すことができます。
しかし、変数に保存しようとしたり、戻り値として返そうと
したときには別の型になってしまいます。
list 27 function0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# include <iostream >
int succ0 (int i) { return i+1; }
struct succ1 {
int operator () (int i) { return i+1; }
};

int main(int , char **) {
int (*f0)(int) = succ0;
succ1 f1;
std :: cout << f0 (1) << std :: endl;
std :: cout << f1 (1) << std :: endl;
}
そこで関数の型として、同じ物を同じ型に封じ込められるよ
うにした便利なものとして、std::function があります。
list 28 function1.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# include <iostream >
# include <functional >
int succ0 (int i) { return i+1; }
struct succ1 {
int operator () (int i) { return i+1; }
};
int main(int , char **) {
std :: function <int(int)> f0 = succ0;
std :: function <int(int)> f1 = succ1 ();
std :: cout << f0 (1) << std :: endl;
std :: cout << f1 (1) << std :: endl;
}
14 ラムダ式
さて次のようなことがしたいとします。
list 29 addsth0.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# include <iostream >
class add_sth {
int x;
public :
add_sth (int _x) : {x=_x ;}
int operator () (int y) const {
return x+y;
}
};
int main(int , char **) {
int x = 5;
auto f = add_sth (x);
std :: cout << f(10) << std :: endl; // 15
}
これをもっと簡単に書く方法として、ラムダ式があります。
list 30 addsth1.cpp
1
2
3
4
5
6
7
8
9

# include <iostream >
int main(int , char **) {
int x = 5;
auto f = [x]( int y){ return x+y; };
std :: cout << f(10) << std :: endl; // 15
}

見慣れない式がありますが、これがラムダ式です。
ラムダ式の文法を解説します。BNF で書くと以下のとおり
です。
⟨lambda-expression⟩ ::= ⟨lambda-introducer ⟩ [⟨lambda-parameter-declaration⟩]
⟨compound-statement ⟩
⟨lambda-introducer ⟩ ::= ‘[’ [⟨lambda-capture ⟩] ‘]’
⟨lambda-capture ⟩ ::= ⟨capture-default ⟩ | ⟨capture-list ⟩ | ⟨capture-default ⟩ ‘,’
⟨capture-list ⟩
⟨capture-default ⟩ ::= ‘&’| ‘=’
⟨capture-list ⟩ ::= ⟨capture ⟩ ‘|’ ⟨capture-list ⟩ , ⟨capture ⟩
⟨capture ⟩ ::= ⟨identifier ⟩ | ‘&’ identifier | ‘this’
⟨lambda-parameter-declaration⟩ ::= ‘(’ [⟨lambda-parameter-declaration-list ⟩] ‘)’
[⟨mutable-specification⟩] [⟨exception-specification⟩]
[⟨lambda-return-type-clause ⟩]
⟨lambda-parameter-declaration-list ⟩ ::= ⟨lambda-parameter ⟩ | ⟨lambda-parameter ⟩
‘,’ ⟨lambda-parameter-declaration-list ⟩
⟨lambda-parameter ⟩ ::= ⟨decl-specifier-seq⟩ ⟨declarator ⟩
⟨lambda-return-type-clause ⟩ ::= ‘->’ ⟨type-id ⟩
Working Draft, Standard for Programming Language C++(N3337) p88 を基に作成
最初の [] で囲われている部分が、lambda-introducer です。
ここにキャプチャしたい変数名を書きます。
最初の例では、コンストラクタで与えられた x をコピーして
保存していますがそれに当たります。

&を変数の前に付けないと、コピーによってキャプチャしま
す。キャプチャ元の変数が解体されたりしても問題ありま
せん。
&を変数の前につけるとコピーして保存するのでなく、参照
によってキャプチャするようになります。参照元が変更され
るとそれに従います。
[] 内のリストの先頭に [=] や [=, x] のように=を書いた場合は
ラムダ式内で使用した変数が暗黙的にコピーでキャプチャさ
れます。

[] 内のリストの先頭に [&] や [&, x] のように&を書いた場合は
ラムダ式内で使用した変数が暗黙的に参照でキャプチャされ
ます。
デフォルトではラムダ式の operator() は const で宣言されま
す。mutable をつけた場合、const が外れます。
次の () で囲われている部分が、
lambda-parameter-declaration です。普通の関数と同じよう
にパラメータを書きます。引数なしの関数オブジェクトを書
く場合はここを省略できます。
最後の {} で囲われている部分は compound-statement で、普
通の関数と書くべきことは同じです。
さてこのように書くと、どう表示されるでしょうか。
1
2
3
4
5
6
7
8
9
10
11
12

int a = 1, b = 1, c = 1;
auto m1 = [a, &b, &c]() mutable {
auto m2 = [a, b, &c]() mutable {
std :: cout << a << b << c;
a = 4; b = 4; c = 4;
};
a = 3; b = 3; c = 3;
m2 ();
};
a = 2; b = 2; c = 2;
m1 ();
std :: cout << a << b << c;

Working Draft, Standard for Programming Language C++(N3337) p91 より引用
15 演習問題
• 次のような設計でオブジェクティブにコーティングしてみ
よう!
– main 関数は標準入力から文字列を受け取って一文字つ
づ、オブジェクト A に投げる。
– オブジェクト A は一文字つづ渡されるデータを集約す
る。改行が送られてくるまではデータをプールしておい
て、改行が来たらまとめて文字列としてオブジェクト B
に投げる。
– オブジェクト B は投げられた文字列を単純に表示する。
• std::vector と std::shared ptr の仕様を各自調べて、
practice::vector と practice::shared ptr を作ってみよう!
16 Reference
http://www.cplusplus.com/
http://en.cppreference.com/w/
http://www.openstd.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
17 Lisence
The text of this document is distributed under the Creative
Commons Attribution-ShareAlike 2.0 License.

Más contenido relacionado

La actualidad más candente

Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11nekko1119
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性Hibiki Yamashiro
 
Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Keisuke Fukuda
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるShintaro Fukushima
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competitionyak1ex
 
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesBoost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesShintarou Okada
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチンyohhoy
 
C++ lecture-2
C++ lecture-2C++ lecture-2
C++ lecture-2sunaemon
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプKohsuke Yuasa
 
Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説JPCERT Coordination Center
 
Flow.js
Flow.jsFlow.js
Flow.jsuupaa
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」Mr. Vengineer
 
templateとautoの型推論
templateとautoの型推論templateとautoの型推論
templateとautoの型推論MITSUNARI Shigeo
 
Boost.Coroutine
Boost.CoroutineBoost.Coroutine
Boost.Coroutinemelpon
 
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~Fujio Kojima
 

La actualidad más candente (20)

Visual C++で使えるC++11
Visual C++で使えるC++11Visual C++で使えるC++11
Visual C++で使えるC++11
 
競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性競技プログラミングにおけるコードの書き方とその利便性
競技プログラミングにおけるコードの書き方とその利便性
 
Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12Effective modern C++ 勉強会 #3 Item 12
Effective modern C++ 勉強会 #3 Item 12
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみる
 
C++0x in programming competition
C++0x in programming competitionC++0x in programming competition
C++0x in programming competition
 
Emcjp item21
Emcjp item21Emcjp item21
Emcjp item21
 
C++14 Overview
C++14 OverviewC++14 Overview
C++14 Overview
 
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core GuidelinesBoost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
Boost.勉強会#19東京 Effective Modern C++とC++ Core Guidelines
 
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
 
C++ lecture-2
C++ lecture-2C++ lecture-2
C++ lecture-2
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプ
 
Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説Javaセキュアコーディングセミナー東京第1回演習の解説
Javaセキュアコーディングセミナー東京第1回演習の解説
 
Flow.js
Flow.jsFlow.js
Flow.js
 
C#6.0の新機能紹介
C#6.0の新機能紹介C#6.0の新機能紹介
C#6.0の新機能紹介
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」TensorFlow XLA 「XLAとは、から、最近の利用事例について」
TensorFlow XLA 「XLAとは、から、最近の利用事例について」
 
Map
MapMap
Map
 
templateとautoの型推論
templateとautoの型推論templateとautoの型推論
templateとautoの型推論
 
Boost.Coroutine
Boost.CoroutineBoost.Coroutine
Boost.Coroutine
 
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
C# 式木 (Expression Tree) ~ LINQをより深く理解するために ~
 

Destacado

Looking For Older Men
Looking For Older MenLooking For Older Men
Looking For Older Mencernotavet
 
Central dalmatia on_facebook_efst_2014_publish
Central dalmatia on_facebook_efst_2014_publishCentral dalmatia on_facebook_efst_2014_publish
Central dalmatia on_facebook_efst_2014_publishMateo Perak
 
C++ lecture-0
C++ lecture-0C++ lecture-0
C++ lecture-0sunaemon
 
Profeina - przedstawienie zespołu
Profeina - przedstawienie zespołuProfeina - przedstawienie zespołu
Profeina - przedstawienie zespołuProfeina
 
PR case study: Profeina dla BlaBlaCar
PR case study: Profeina dla BlaBlaCarPR case study: Profeina dla BlaBlaCar
PR case study: Profeina dla BlaBlaCarProfeina
 
p1 public health
p1 public healthp1 public health
p1 public healthjessejess29
 

Destacado (11)

Looking For Older Men
Looking For Older MenLooking For Older Men
Looking For Older Men
 
Fireworks Credentials
Fireworks CredentialsFireworks Credentials
Fireworks Credentials
 
softwss
softwsssoftwss
softwss
 
Bribe yourb team
Bribe yourb teamBribe yourb team
Bribe yourb team
 
Central dalmatia on_facebook_efst_2014_publish
Central dalmatia on_facebook_efst_2014_publishCentral dalmatia on_facebook_efst_2014_publish
Central dalmatia on_facebook_efst_2014_publish
 
Media institution
Media institution Media institution
Media institution
 
C++ lecture-0
C++ lecture-0C++ lecture-0
C++ lecture-0
 
Bribe your team
Bribe your teamBribe your team
Bribe your team
 
Profeina - przedstawienie zespołu
Profeina - przedstawienie zespołuProfeina - przedstawienie zespołu
Profeina - przedstawienie zespołu
 
PR case study: Profeina dla BlaBlaCar
PR case study: Profeina dla BlaBlaCarPR case study: Profeina dla BlaBlaCar
PR case study: Profeina dla BlaBlaCar
 
p1 public health
p1 public healthp1 public health
p1 public health
 

Similar a C++ lecture-1

ぱっと見でわかるC++11
ぱっと見でわかるC++11ぱっと見でわかるC++11
ぱっと見でわかるC++11えぴ 福田
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another sideKiwamu Okabe
 
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...Masahiro Sakai
 
怪しいWindowsプログラミング
怪しいWindowsプログラミング怪しいWindowsプログラミング
怪しいWindowsプログラミングnagoya313
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいdigitalghost
 
Brief introduction of Boost.ICL
Brief introduction of Boost.ICLBrief introduction of Boost.ICL
Brief introduction of Boost.ICLyak1ex
 
1075: .NETからCUDAを使うひとつの方法
1075: .NETからCUDAを使うひとつの方法1075: .NETからCUDAを使うひとつの方法
1075: .NETからCUDAを使うひとつの方法NVIDIA Japan
 
PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方Satoshi Nagayasu
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターンMoriharu Ohzu
 
PL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database AnalyticsPL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database AnalyticsKohei KaiGai
 
Lambda in template_final
Lambda in template_finalLambda in template_final
Lambda in template_finalCryolite
 
Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Mr. Vengineer
 
C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編道化師 堂華
 
RETEアルゴリズムを使いこなせ
RETEアルゴリズムを使いこなせRETEアルゴリズムを使いこなせ
RETEアルゴリズムを使いこなせMasahiko Umeno
 

Similar a C++ lecture-1 (20)

Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
ぱっと見でわかるC++11
ぱっと見でわかるC++11ぱっと見でわかるC++11
ぱっと見でわかるC++11
 
Slide
SlideSlide
Slide
 
Dive into RTS - another side
Dive into RTS - another sideDive into RTS - another side
Dive into RTS - another side
 
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
“Symbolic bounds analysis of pointers, array indices, and accessed memory reg...
 
怪しいWindowsプログラミング
怪しいWindowsプログラミング怪しいWindowsプログラミング
怪しいWindowsプログラミング
 
C++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みくださいC++コンパイラ GCCとClangからのメッセージをお読みください
C++コンパイラ GCCとClangからのメッセージをお読みください
 
C++0x総復習
C++0x総復習C++0x総復習
C++0x総復習
 
Brief introduction of Boost.ICL
Brief introduction of Boost.ICLBrief introduction of Boost.ICL
Brief introduction of Boost.ICL
 
1075: .NETからCUDAを使うひとつの方法
1075: .NETからCUDAを使うひとつの方法1075: .NETからCUDAを使うひとつの方法
1075: .NETからCUDAを使うひとつの方法
 
PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
 
emc++ chapter32
emc++ chapter32emc++ chapter32
emc++ chapter32
 
VerilatorとSystemC
VerilatorとSystemCVerilatorとSystemC
VerilatorとSystemC
 
PL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database AnalyticsPL/CUDA - GPU Accelerated In-Database Analytics
PL/CUDA - GPU Accelerated In-Database Analytics
 
Lambda in template_final
Lambda in template_finalLambda in template_final
Lambda in template_final
 
Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析Cloud TPU Driver API ソースコード解析
Cloud TPU Driver API ソースコード解析
 
C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編
 
RETEアルゴリズムを使いこなせ
RETEアルゴリズムを使いこなせRETEアルゴリズムを使いこなせ
RETEアルゴリズムを使いこなせ
 

C++ lecture-1