C++ & Bitcoin Core 注意点 Lab - Karl-Johan Alm 2017 Digital Garage. All rights reserved. Redistribution or public display not permitted without w

Similar documents
このセッションについて RPC アプリの作成 : 注意点とベストプラクティス ( 前半 ) RPC のコードを触ろう RPC アプリの作成 : 注意点とベストプラクティス ( 後半 ) 2

関数 C 言語は関数の言語 関数とは 関数の定義 : f(x) = x * x ; 使うときは : y = f(x) 戻り値 引数

情報処理Ⅰ演習

Microsoft PowerPoint Java基本技術PrintOut.ppt [互換モード]

Slide 1

Javaセキュアコーディングセミナー2013東京第1回 演習の解説

Microsoft PowerPoint - prog03.ppt

Microsoft PowerPoint ppt

基礎プログラミング2015

gengo1-11

Microsoft PowerPoint - ruby_instruction.ppt

PowerPoint プレゼンテーション


Microsoft PowerPoint - 計算機言語 第7回.ppt

Agenda Transaction とは インプットとは アウトプットとは インプットとアウトプットの関係 手数料 (fee) とは UTXO(Unspent Transaction Output) とは 2

Microsoft PowerPoint - 09.pptx

memo

C のコード例 (Z80 と同機能 ) int main(void) { int i,sum=0; for (i=1; i<=10; i++) sum=sum + i; printf ("sum=%d n",sum); 2

とても使いやすい Boost の serialization

Microsoft PowerPoint - class2-OperatorOverLoad.pptx

02: 変数と標準入出力

02: 変数と標準入出力

C プログラミング演習 1( 再 ) 2 講義では C プログラミングの基本を学び 演習では やや実践的なプログラミングを通して学ぶ

Condition DAQ condition condition 2 3 XML key value

CプログラミングI

Microsoft PowerPoint - exp2-02_intro.ppt [互換モード]

Microsoft Word - no15.docx

Microsoft PowerPoint - chap10_OOP.ppt

(1) プログラムの開始場所はいつでも main( ) メソッドから始まる 順番に実行され add( a,b) が実行される これは メソッドを呼び出す ともいう (2)add( ) メソッドに実行が移る この際 add( ) メソッド呼び出し時の a と b の値がそれぞれ add( ) メソッド

ex12.dvi

Microsoft Word - no11.docx

02: 変数と標準入出力

1-4 int a; std::cin >> a; std::cout << "a = " << a << std::endl; C++( 1-4 ) stdio.h iostream iostream.h C++ include.h 1-4 scanf() std::cin >>

Microsoft PowerPoint - CproNt02.ppt [互換モード]

Microsoft Word - no202.docx

プログラミング基礎I(再)

C言語講座

kiso2-09.key

Prog1_10th

/*Source.cpp*/ #include<stdio.h> //printf はここでインクルードして初めて使えるようになる // ここで関数 average を定義 3 つの整数の平均値を返す double 型の関数です double average(int a,int b,int c){

バイオプログラミング第 1 榊原康文 佐藤健吾 慶應義塾大学理工学部生命情報学科

PowerPoint プレゼンテーション

double 2 std::cin, std::cout 1.2 C fopen() fclose() C++ std::fstream 1-3 #include <fstream> std::fstream fout; int a = 123; fout.open( "data.t

Microsoft PowerPoint pptx

design_pattern.key

Program Design (プログラム設計)

関数の動作 / printhw(); 7 printf(" n"); printhw(); printf("############ n"); 4 printhw(); 5 関数の作り方 ( 関数名 ) 戻り値 ( 後述 ) void である. 関数名 (

Microsoft PowerPoint - 説明3_if文switch文(C_guide3)【2015新教材対応確認済み】.pptx

Microsoft Word - C言語研修 C++編 3.doc

JavaプログラミングⅠ

Taro-ファイル処理(公開版).jtd

新・明解C言語 実践編

gengo1-12

PowerPoint プレゼンテーション

8 / 0 1 i++ i 1 i-- i C !!! C 2

第二回独習 Java ゼミ 第二章クラスとメソッド 2.1 メソッドの構造 2.2 静的メソッドと静的変数の概要 2.3 インスタンスメソッドとインスタンス変数の概要 2.4 Integerクラス 2006/04/19 神津健太

Microsoft PowerPoint - prog04.ppt

cpp4.dvi

PowerPoint プレゼンテーション

memo

2017_08_ICN研究会_印刷用

Java講座

新・明解C言語で学ぶアルゴリズムとデータ構造

cpp1.dvi

02: 変数と標準入出力

Microsoft PowerPoint - prog09.ppt

Microsoft PowerPoint - prog09.ppt

JavaプログラミングⅠ

RX ファミリ用 C/C++ コンパイラ V.1.00 Release 02 ご使用上のお願い RX ファミリ用 C/C++ コンパイラの使用上の注意事項 4 件を連絡します #pragma option 使用時の 1 または 2 バイトの整数型の関数戻り値に関する注意事項 (RXC#012) 共用

プログラミング入門1

スライド 1

JAVA とテンプレート

/* do-while */ #include <stdio.h> #include <math.h> int main(void) double val1, val2, arith_mean, geo_mean; printf( \n ); do printf( ); scanf( %lf, &v

情報工学実験 C コンパイラ第 2 回説明資料 (2017 年度 ) 担当 : 笹倉 佐藤


ソフトゼミC 第二回 C++の基礎

* ライブラリ関数 islower(),toupper() を使ったプログラム 1 /* 2 Program : trupper.c 3 Student-ID : K 4 Author : TOUME, Kouta 5 Comments : Used Library function i

C言語7

gengo1-12

デジタル表現論・第6回

Exam : 1z1-809-JPN Title : Java SE 8 Programmer II Vendor : Oracle Version : DEMO Get Latest & Valid 1z1-809-JPN Exam's Question and Answers 1 from Ac

gengo1-12

コマンドラインから受け取った文字列の大文字と小文字を変換するプログラムを作成せよ 入力は 1 バイトの表示文字とし アルファベット文字以外は変換しない 1. #include <stdio.h> 2. #include <ctype.h> /*troupper,islower,isupper,tol

スライド 1

PowerPoint プレゼンテーション

C 言語の式と文 C 言語の文 ( 関数の呼び出し ) printf("hello, n"); 式 a a+4 a++ a = 7 関数名関数の引数セミコロン 3 < a "hello" printf("hello") 関数の引数は () で囲み, 中に式を書く. 文 ( 式文 ) は

Microsoft Word - VBA基礎(6).docx

データ構造とアルゴリズム論

slide5.pptx


02: 変数と標準入出力

第2回講義:まとめ

た場合クラスを用いて 以下のように書くことが出来る ( 教科書 p.270) プログラム例 2( ソースファイル名 :Chap08/AccountTester.java) // 銀行口座クラスとそれをテストするクラス第 1 版 // 銀行口座クラス class Account String name

SuperH RISC engineファミリ用 C/C++コンパイラパッケージ V.7~V.9 ご使用上のお願い

ファイル入出力

PowerPoint プレゼンテーション

02: 変数と標準入出力

メソッドのまとめ

PowerPoint プレゼンテーション

VB.NETコーディング標準

Transcription:

C++ & Bitcoin Core 注意点 まとめ @DG Lab - Karl-Johan Alm 2017 Digital Garage. All rights reserved. Redistribution or public display not permitted without written permission from Digital Garage.

逃げられる前に言っておこう これは C++ を教えるセッションというより C++ にあまり慣 れていない人が Bitcoin Core の コードを開くと混乱しそうな機能の注意点を並 べていくセッションである!

Agenda const Ref(&) と pointer(*) Ref(&) と by-ref (&) friends virtual テンプレート const と by-ref (&) の関係 operators

const( 定数 ) Objective-C の (im)mutability( 不変的 変動的 ) と似ている 例 : A mya; const A mycnsta; class A { 種類 : 変更実行可能? 変更実行可能? int a; 変数 const int b; const 変数 void m(); 関数 const int n(); void o() const; const 関数 };

const( 定数 ) class A { A const A public: R W X R W X int a = 1; const int b = 2; int m() {return 3;}; const int n() {return 4;}; int o() const {return 5;}; };

const( 定数 ) の実行例 A mya; の場合 const A myconsta; の場合 A mya; printf("a:%d\n", mya.a); mya.a = 10; printf("a:%d\n", mya.a); // Compile Error // mya.b = 20; printf("b:%d\n", mya.b); printf("m:%d\n", mya.m()); printf("n:%d\n", mya.n()); printf("o:%d\n", mya.o()); a:1 a:10 b:2 m:3 n:4 o:5 const A myconsta; printf("a:%d\n", myconsta.a); // Compile Error // myconsta.a = 10; // mya.b = 20; printf("b:%d\n", myconsta.b); // Compile Error // printf("m:%d\n", myconsta.m()); // printf("n:%d\n", myconsta.n()); printf("o:%d\n", myconsta.o()); a:1 b:2 o:5

const( 定数 ) const <type> myfun() は定数の <type> を返す 例 : class B { private: A mya; Public: const A geta() { return mya; } }; int main(void) { somea.m(); // できない B myb; somea.o(); // できる const A somea = myb.geta(); somea.a = 38;// できない

const( 実行例 ) A mya; の場合 class B { private: A mya; public: const A geta() { return mya; }; }; B myb; const A somea = myb.geta(); printf("a:%d\n", somea.a); printf("b:%d\n", somea.b); // Compile Error // somea.a = 10; // somea.b = 10; // printf("m:%d\n", somea.m()); // printf("n:%d\n", somea.n()); printf("o:%d\n", somea.o()); a:1 b:2 o:5

Reference(&) と pointer(*) C 言語 : int a = 123; a = 123, &a = 0x7fa..b ( アドレス ); *a = < 爆発 > int* b = NULL; b = NULL; &b = 0x7ef..c( アドレス );*b = < 爆発 > b = &a; a =???; &a =???; b =????; &b =???; *b =??? *b = 456; a =???; &a =???; b =????; &b =???; *b =??? int** c = &b; c =???; *c =???; **c =???; a, &a, b, &b, *b? void myfun(int *x) を実行するときに int a をパラメーターに入れたい時はどう書けば?

Reference(&) と pointer(*)< 実行例 > int a = 123; printf("int a = 123;\n"); printf("a is %-20d, &a is %-20p, *a is error\n", a, &a); int *b = NULL; printf("int *b = NULL;\n"); printf("b is %-20p, &b is %-20p, *b is error\n", b, &b); b = &a; printf("b = &a;\n"); printf("a is %-20d, &a is %-20p, *a is error\n", a, &a); printf("b is %-20p, &b is %-20p, *b is %d\n", b, &b, *b); *b = 456; printf("*b = 456;\n"); printf("a is %-20d, &a is %-20p, *a is error\n", a, &a); printf("b is %-20p, &b is %-20p, *b is %d\n", b, &b, *b); int **c = &b; printf("int **c = &b;\n"); printf("a is %-20d, &a is %-20p, *a is error\n", a, &a); printf("b is %-20p, &b is %-20p, *b is %d\n", b, &b, *b); printf("c is %-20p, *c is %-20p, **c = %d\n", c, *c, **c); int a = 123; a is 123, &a is 0x7ffe146f9154, *a is error int *b = NULL; b is (nil), &b is 0x7ffe146f9158, *b is error b = &a; a is 123, &a is 0x7ffe146f9154, *a is error b is 0x7ffe146f9154, &b is 0x7ffe146f9158, *b is 123 *b = 456; a is 456, &a is 0x7ffe146f9154, *a is error b is 0x7ffe146f9154, &b is 0x7ffe146f9158, *b is 456 int **c = &b; a is 456, &a is 0x7ffe146f9154, *a is error b is 0x7ffe146f9154, &b is 0x7ffe146f9158, *b is 456 c is 0x7ffe146f9158, *c is 0x7ffe146f9154, **c = 456

Reference(&) と pointer(*) 一つ 重要なポイントがある void myfun1a(type v) v の変更は 呼出元には反映されない! void myfun1b(type* vptr) vptr の指すオブジェクトの変更が 呼出元でも反映される!

Reference(&) と pointer(*) void myfun2a(int i) { i = i * 2; } void myfun2b(int* i) { *i = *i * 2; } int a = 3; myfun2a(a); // a == 3 myfun2b(&a); // a == 6

Reference(&) と by-reference (&) class Elephant { private: char hugechar[1000000]; // 1MB の変数 public: Elephant() { printf("new elephant %p created\n", this); } void greet(elephant other) { printf("%p greets %p\n", this, &other); printf("%p vs %p\n", hugechar, other.hugechar); } };

Reference(&) と by-reference (&) さてと int main() { Elephant myelephant; myelephant.greet(myelephant); // 自分自身を渡してみる } どうなるこれ?

Reference(&) と by-reference (&) こうなる : New elephant 0x7fff545fe148 created 0x7fff545fe148 greets 0x7fff54415cc0 0x7fff545fe148 vs 0x7fff54415cc0 つまり 呼ぶ時にコピーしてから引き渡す あまりに大きい引数は 一時的にメモリが大量に必要になったり コピー処理自体のオーバーヘッドも無視できなくなるため 望ましくない

Reference(&) と by-reference (&) 0x7fff545fe148 Image by AnimalsClipart

Reference(&) と by-reference (&) 0x7fff545fe148 greet(0x7fff 545fe148)

Reference(&) と by-reference (&) 0x7fff545fe148 0x7fff54415cc0 greet(0x7fff 545fe148)

Reference(&) と by-reference (&) 0x7fff545fe148 0x7fff54415cc0 greet(0x7fff 545fe148) void greet(elephant other) { this 0x7fff545fe148 other 0x7fff54415cc0

Reference(&) と by-reference (&) 0x7f 0x7fff545fe148

Reference(&) と by-reference (&) 0x7fff545fe148

Reference(&) と by-reference (&) C 言語での解決方法 ( 分かりやすくするためにクラスを使う ): // class Elephant 内 void greet2(elephant* other) { printf( %p greets %p\n, this, other); printf("%p vs %p\n", hugechar, other->hugechar); } // そして, main では myelephant.greet2(&myelephant);

Reference(&) と by-reference (&) C++ ではもっと分かりやすい方法がある これはby-referenceと言って自動的に 1 コピーしないでオブジェクトをそのまま引き渡す ( 速い ) 2 そのまま引き渡す=オブジェクトの中身は変えられる (mutability 機能 ) となる void donotcopy(elephant& other) // by-reference パラメータ 2 は変えられると困る場合もある

const と by-reference の関係 const な変数やインスタンスを持っている時には const 関数しか呼べない public の変数は変えられない const のままでしか使えないという制限がある void foo(const Elephant& myelephant) という関数の呼び出し方であれば myelephant は絶対に変わらない (foo が違う関数を呼び出しても ) このため コピーして欲しくない ( 遅いから ) し 変更もして欲しくない ( セーフティの為 ) という問題が解決する

const と by-reference の関係 void bar(elephant& e) void zed(const Elephant& e) void foo(const Elephant& e) { bar(e); // コンパイル時にエラーが出る zed(e); // エラーは出ない zedもeを変えられない }

Reference, by-reference, pointer 言語アクセスコピーされる変えられる <T> x C/C++ x.var はい いいえ <T>& x C++ x.var いいえ はい <T>* x C/C++ x->var いいえ はい

operator( 演算子 ) クラスで演算子を多重定義することができる ただし演算子の元々の機能とかけ離れた定義にすると可読性が下がる class A { int main() { public: A mya; int i = 5; int foo = 38; A& operator=(int x) { mya = foo; i = x; printf( mya.i=%d\n, mya.i); } // mya.i = 38 }; }

friend( 友達 ) 機能 C++ では friend という特殊な機能が付いている friend に指定されると指定元クラスの private 変数 関数が使えるようになる class A { class B { private: public: int privint; void poke(a& ana) { public: ana.privint = 38; friend class B; } }; }; クラスを friend にすることもできるし

friend( 友達 ) 機能 メソッドも friend にできる class A { private: int privint = 0; public: friend bool operator==(const A& first, const A& second); }; bool operator==(const A& first, const A& second) { return first.privint == second.privint; } // A の外なのに privint にアクセスできる

friend( 友達 ) 機能 int main() { A a1; A a2; // a1.privint =??? a2.privint =??? B myb; myb.poke(a2);// a1.privint =??? a2.privint =??? printf( same? %d\n, a1 == a2); // 出力 =??? myb.poke(a1); printf( same? %d\n, a1 == a2); // 出力 =??? } B.poke void poke(a& ana) { ana.privint = 38; }

friend( 友達 ) 機能 よく使う場面 : さまざまな operator class A { private: int i = 0; friend A& operator+(const A& one, const A& other); }; // mya + myothera -> new A where i = mya.i + myothera.i friend A& operator+(const A& one, const A& other) { A *tmp = new A; tmp->i = one.i + other.i; return *tmp; }

const, friend ( 読 (r) 書 (w) 呼 (x) 可 r 可 wx 不可 rwx 不可 ) ( 注意 : <t> < 名 >( ) const という関数は呼 (x) 可 ) public private Non-const 自分 Friend 他人 自分 Friend 他人 Const 自分 Friend 他人 自分 Friend 他人

virtual class A { class B : public A { public: public: void greet() { void greet() { printf("hello!\n"); printf("hi there!\n"); } } }; }; void greetfun(a& a) { a.greet(); } int main() { A mya; B myb; greetfun(mya); greetfun(myb); // 出力は? }

virtual class A { class B : public A { public: public: virtual void greet() { void greet() { printf("hello!\n"); printf("hi there!\n"); } } }; }; void greetfun(a& a) { a.greet(); } int main() { A mya; B myb; greetfun(mya); greetfun(myb); // 出力は? }

virtual< 実行例 > class A { public: virtual void greet() { printf("hello!\n"); } }; class B: public A { public: void greet() { printf("hi there!\n"); } }; A mya; B myb; greetfun(mya); greetfun(myb); void greetfun(a& a) { a.greet(); } virtual なし virtual あり Hello! Hello! Hello! Hi there!

テンプレート C++ にはテンプレートの機能がある テンプレートによって使用する場面に合わせた関数やクラスが生成される 例 : 以下のような関数があるとする template<typename T> void print(t myt) { std::cout << myt.tostring() << std::endl; }

テンプレート 二つの 全く関係ないクラスに同じシグネチャのメソッドを作る class A { class B { std::string tostring() { std::string tostring() { return mya ; return myb ; } } }; };

テンプレート するとこういう書き方ができる : int main() { A ana; B ab; print(ana); print(ab); } // mya - print(a myt); // myb - print(b myt); クラスもテンプレートとして作ることができる

テンプレート 例 : template<typename T> MyClass<int> myintclass; class MyClass { int a = 5; public: myintclass.print(a); void print(t somet) { std::cout << somet << std::endl; } }; さて テンプレートで何ができるか考えよう!

テンプレート C++ では標準ライブラリ (Standard Template Library) としてテンプレートベースのクラスが多数存在し よく使われている その中でも std::vector std::map がおそらく一番よく使われている

テンプレート タスク :printvec という関数 ( クラスは不要 ) を作って下さい 例 : std::vector<a> avec; std::vector<b> bvec; avec.resize(2); bvec.resize(3); printvec(avec); // 出力 ( 二行 ):mya mya printvec(bvec); // 出力 ( 三行 ):myb myb myb

テンプレート < 解答例 > class A { public: std::string tostring() { return "mya"; } }; class B { public: std::string tostring() { return "myb"; } }; template<typename T> void printvec(t vect) { for (auto item : vect) { printf("%s\n", item.tostring().c_str()); } } std::vector<a> avec; std::vector<b> bvec; avec.resize(2); bvec.resize(3); printvec(avec); printvec(bvec); mya mya myb myb myb

Bitcoin Core で使われているテンプレート Serialize/de-Serialize という機能でテンプレートが非常によく使われている ネット上でのやり取り (block transaction の送信等 ) ディスクとの書込読込 (chain undo データ utxodb 等 ) RPC 環境でのやり取り 検証 ハッシュの作成 等等!

Bitcoin Core で使われているテンプレート 主にこのように使われている : serialize.h の中にあらゆるタイプの基本 serialize 関数がある

Bitcoin Core で使われているテンプレート 各クラスに ADD_SERIALIZE_METHODS; というマクロが入っている そして template <typename Stream, typename Operation> inline void SerializationOp(Stream& s, Operation ser_action, int ntype, int nversion) で読み書き対象のデータを READWRITE メソッドに引き渡す

Bitcoin Core で使われているテンプレート 例 (class COutPoint): ADD_SERIALIZE_METHODS; template <typename Stream, typename Operation> inline void SerializationOp(Stream& s, Operation ser_action, int ntype, int nversion) { READWRITE(hash); READWRITE(n); }

Bitcoin Core で使われているテンプレート 読み込み時と書き込み時で特有の処理が必要な場合の切り分けには ser_action.forread() を参照する 例 ) SerializeTransaction: if (ser_action.forread()) { // 読込 const_cast<std::vector<ctxin>*>(&tx.vin)->clear(); [...] } else { // 書込 [...] }

@DG Lab - Karl-Johan Alm 48