Javaとかc#とか最近の言語使いのためのc++入門

6,135 views

Published on

0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
6,135
On SlideShare
0
From Embeds
0
Number of Embeds
193
Actions
Shares
0
Downloads
12
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide

Javaとかc#とか最近の言語使いのためのc++入門

  1. 1. JavaとかC#とか 最近の言語使いのためのC++入門 C++はやればできる子です
  2. 2. 極めて高級な言語の普及 C++は比較的低級なので難し く感じる Ruby とか C#と か Java とか 2 初めて学習する言語が極めて高級であることが増えてきている
  3. 3. 高級な言語と低級な言語 低級 難しい 低級じゃないと実現 できないことが たくさんの複雑な仕 様には向かない 高級 簡単 一般的なことしかでき ない たくさんの複雑な仕 様に向く 3
  4. 4. C++は本当に低級な部分から学ぶべき? • 「標準C++を新しい言語として学ぶ」 • 「ストラウストラップのプログラミング入門」 – Cと互換の部分の一部はC++の中でも、特に初心者 は触るべきではない応用部分 – 初心者はもっとC++の基本部分から学ぶべき • つまり、C#などと似た部分から学ぶべき 4 C++はCの拡張だ からCから学ぶのが 良い? それは間違いです
  5. 5. C++の適用範囲 • Cと同じことも、C#と同じこともできます C C# Java Visual Basic C++ 5
  6. 6. メモリ管理 JavaやC#にくらべ、C++ のメモリ管理は難しいとい われています そんなことはあ りません。良い 方法はいくつも 用意されていま す。 6
  7. 7. メモリ管理(スコープ) • スコープ – Cからある仕組み – 確保したメモリは、スコープの終わりで破棄 for (int i = 0; i < 5; i++) { string s = "ABC"; cout << s << endl; } 7
  8. 8. メモリ管理(クラス) • スコープで解決できない問題 – オブジェクト指向では、データが塊としてツリー上 に確保される – ツリーの枝は、最初に確保したプログラムのあず かり知らぬところで増えたり減ったりする • クラスを使って解決(RAII) – メンバ変数にポインタを利用していなければ、ス コープと同じように破棄される – ポインタの参照先は、自インスタンスが破棄され る時に、子インスタンスを責任を持って破棄する 8
  9. 9. メモリ管理(スマートポインタ) • クラスで解決できない問題 – 戻り値などで、オブジェクトの外に出されるオブ ジェクトはクラスでは管理できない • スマートポインタ(std::shared_ptr) – 参照カウンタ方式で、使われなくなったら自動的 にガベージコレクト 9 shared_ptr<ofstream> getStream() { return make_shared<ofstream>("C:test.txt"); } いっそこれだけしか使わない ことにすれば、C#やJavaと ほぼ同じになります。
  10. 10. ポインタ C++はポインタを使わな くてはならないから難し い、と言われています 実際には、使おうと思 わなければ無理に使 う必要はありません。 10
  11. 11. ポインタ(参照) • 参照 – 引数の参照渡しは参照を渡せばよい – ポインタとか意識せずそのまま使えます。 • JavaとかC#と同じ。 void func(int& a) { a += 2; } 11
  12. 12. ポインタ(配列・文字列) • 配列はポインタを意識しないといけません – std::vectorとかを使いましょう • 文字列もポインタを意識しないといけません – std::stringを使いましょう vector<int> v; string s = "AAA"; 12
  13. 13. ポインタ(イテレータ) • コレクションを頭から順番に利用するときにポ インタが使われます – イテレータを使いましょう – Range based forも使えます 13 for (auto it = vec.begin(); it != vec.end(); ++it) { cout << *it << endl; } for(auto item : vec) { cout << item << endl; }
  14. 14. ポインタ(スマートポインタ) • ヒープ領域やポリモーフィズムを使うときはポ インタが必要 – スマートポインタを使いましょう 14 shared_ptr<ofstream> getStream() { return make_shared<ofstream>("C:test.txt"); }
  15. 15. ポインタ(その他) • まれに、これまで挙げた手段が使えない場合 もあります – 引数に関係ない – 配列や文字列ではない – ポインタ演算は行わない – メモリ管理に関係ない • ポインタの難しい部分を全く使わないので、 心配せずにポインタを使いましょう 15
  16. 16. C++で利用できる機能 C++は古くて機 能が少ない? そんなことはあ りません 16
  17. 17. C++で利用できる機能 C++で 利用で きる機能 Cの機能 オブジェ クト指向 ジェネリッ クプログ ラミング 型推論 高階関数 標準C++ ライブラリ Boost C++17 17
  18. 18. Cの機能 • かなり高度なことはできます 18 C標準ライブ ラリ 型シ ステ ム 構造 体 列挙 体 共用 体 C++の新しい機能に置き換えられているものも多いので、 できるだけそっちを使いましょう
  19. 19. オブジェクト指向 • C#やJavaにできることは大体できます • C#やJavaにできないこともできます 19 多重継承 =演算子などのオーバーロード ムーブセマンティック 他 大変多機能 で複雑です
  20. 20. ジェネリックプログラミング 20 • C++なのになんとダックタイピング。 • Dll化が不可能で、ヘッダで配布する必要がある。 • エラーが出たときの解析が非常に大変。 C#やJavaと違って、型システムではなく、テキスト展開 • 型ではなく数字を取るようなことはC#やJavaには不可能 • テンプレートメタプログラミング ただし、問題点はあれ、機能的には大変高機能。
  21. 21. ジェネリックプログラミング • 同じvectorクラスがfloatにもstringにも使え、 型チェックも行われます。 21 vector<double> vf = { 0.3, 0.2, 0.1 }; vf.push_back(0.4); sort(vf.begin(), vf.end()); double f = vf[0]; vector<string> vs = { "CCC", "BBB", "AAA" }; vs.push_back("DDD"); sort(vs.begin(), vs.end()); string s = vs[0];
  22. 22. 型推論 • 型推論 – コンパイラにわかるものはコンパイラに任せる 22 shared_ptr<map<string, int>> v = make_shared<map<string, int>>(); auto v = make_shared<map<string, int>>();
  23. 23. 型推論 • オブジェクトの生成時に力を発揮します 23 map<string, vector<int>> m; vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); m["A"] = v; v.clear(); v.push_back(4); v.push_back(5); m["B"] = v; v.clear(); v.push_back(6); v.push_back(7); v.push_back(8); v.push_back(9); m["C"] = v; map<string, vector<int>> m = { {"A", {1, 2, 3}}, {"B", {4, 5}}, {"C", {6, 7, 8, 9}} };
  24. 24. 高階関数 char* data[] = {"Apple", "Microsoft", "Google", "Oracle", "Dell"}; char deleted = 'O'; resultNum = 0; for(i = 0; i < dataNum; i++){ /* 頭文字がbad以外のもののみを結果として抽出 */ if(data[i][0] != deleted){ result[resultNum++] = data[i]; } } /*文字列数でソート*/ for(i = 0; i < resultNum; i++){ for(j = i + 1; j < resultNum; j++){ if(strlen(result[j]) < strlen(result[i])){ tmp = result[i]; result[i] = result[j]; result[j] = tmp; } } } CREATE TABLE #DATA (S VARCHAR(MAX)) INSERT INTO #DATA(S) VALUES('Apple'), ('Microsoft'), ('Google'), ('Dell'), ('Oracle') DECLARE @DELETED CHAR SET @DELETED = 'O' SELECT S INTO #RESULT FROM #DATA WHERE SUBSTRING(S, 1, 1) <> @DELETED ORDER BY LEN(S) C Transact-SQL 24 CとSQLで、同じ処理を書いてみます Cの書き方と比べ、SQLの方が分かりやすいですね
  25. 25. 高階関数 • ほかの色々な言語で書いてみます data = %w(Apple Microsoft Google Dell Oracle) deleted = "O" result = data .find_all{|s| !s.start_with? deleted} .sort{|l, r| l.size <=> r.size} Ruby var data = new[] { "Apple", "Microsoft", "Google", "Oracle", "Dell" }; var deleted = "O"; var result = from s in data where !s.StartsWith(deleted) orderby s.Length select s; var data = new[] { "Apple", "Microsoft", "Google", "Oracle", "Dell" }; var deleted = "O"; var result = data .Where(s => !s.StartsWith(deleted)) .OrderBy(s => s.Length); Dim data = New String() {"Apple", "Microsoft", "Google", "Oracle", "Dell"} Dim deleted = "O“ Dim result = From s In data Where Not s.StartsWith(deleted) Order By s.Length Select s C# C# (メソッド構文) Visual Basic 最近の言語は、CよりSQLに近い形で書けるものが多いです。 $data = array('Apple', 'Microsoft', 'Google', 'Oracle', 'Dell'); $deleted = 'O'; $result = array_filter($data, function($s) use ($deleted){return substr($s, 0, 1) != $deleted;}); usort($result, function($l, $r){return strlen($l) - strlen($r);}); PHP 25 List<String> data = Arrays.asList("Apple", "Microsoft", "Google", "Oracle", "Dell"); String deleted = "O"; Stream<String> result = data.stream() .filter(s -> !s.startsWith(deleted)) .sorted((l, r)->l.length() - r.length()); Java data = ['Apple', 'Microsoft', 'Google', 'Dell', 'Oracle'] deleted = 'O' result = [x for x in sorted(data, key=len) if not x.startswith(deleted)] Python @data = qw/Apple Microsoft Google Dell Oracle/; $deleted = "O"; @result = sort {length $a <=> length $b} (grep /^[^$deleted].*/, @data); Perl
  26. 26. 高階関数 • さらにいろいろ (def data ["Apple" "Microsoft" "Google" "Oracle" "Dell"]) (def delete O) (sort #(< (count %)(count %2)) (filter #(not (= (first %) delete)) data)) Clojure data = ['Apple', 'Microsoft', 'Google', 'Oracle', 'Dell'] deleted = 'O' result = (s for s in data when s.charAt(0) != deleted) result.sort (l, r) -> l.length - r.length CoffeeScript var data = ['Apple', 'Microsoft', 'Google', 'Oracle', 'Dell']; var deleted = 'O'; var result = data.filter((s) => !s.startsWith(deleted); result.sort((l, r) => l.length - r.length); Dart let data = ["Apple"; "Microsoft"; "Google"; "Oracle"; "Dell"] let deleted = "O" let result = data |> List.filter(fun s -> not(s.StartsWith(deleted))) |> List.sortBy(fun s -> s.Length) F# 26 |data deleted result| data ← #('Apple' 'Microsoft' 'Google' 'Dell' 'Oracle'). deleted ← 'O'. result ← data select:[:s | (s beginsWith: deleted) not]. result ← result sortBy:[:l :r | (l size) < (r size)]. Smalltalk var data = "Apple" :: "Microsoft" :: "Google" :: "Oracle" :: "Dell" :: Nil var deleted = "O" var result = data filter(!_.startsWith(deleted)) sortWith(_.size < _.size) Scala var data = ['Apple', 'Microsoft', 'Google', 'Oracle', 'Dell']; var deleted = 'O' var result = data.filter(function(s){return s.charAt(0) != deleted;}); result.sort(function(l, r){return l.length - r.length;}); JavaScript let data = ['Apple', 'Microsoft', 'Google', 'Oracle', 'Dell']; let deleted = 'O'; let result = data.filter(s=>s.charAt(0) != deleted); result.sort((l, r)=>l.length - r.length); EcmaScript 2015 var data = ['Apple', 'Microsoft', 'Google', 'Oracle', 'Dell'] var deleted = 'O' var result = data.filter(s=>s.charAt(0) != deleted) result.sort((l, r)=>l.length - r.length) TypeScript
  27. 27. 高階関数 • もっといろいろ 27 let data = ["Apple", "Microsoft", "Google", "Oracle", "Dell"] let deleted = "O“ var result = data.filter({ !$0.hasPrefix(deleted) }) result.sort({count($0) < count($1)}) Swift let data = ["Apple", "Microsoft", "Google", "Oracle", "Dell"]; let deleted = "O"; let mut result : Vec<&&str> = data.iter().filter(|s| !s.starts_with(deleted)).collect(); result.sort_by(|l, r|l.chars().count().cmp(&r.chars().count())); Rust auto data = ["Apple", "Microsoft", "Google", "Oracle", "Dell"]; const deleted = 'O'; auto result = data.filter!(s => s[0] != deleted).array; result.sort!((l, r)=>l.length < r.length); D val data = array("Apple", "Microsoft", "Google", "Oracle", "Dell") val deleted = 'O' val result = data.filter{it[0] != deleted} sortBy{it.length} Kotlin NSArray *data = [NSArray arrayWithObjects:@"Apple", @"Microsoft", @"Google", @"Oracle", @"Dell", nil]; NSString *deleted = @"O"; NSIndexSet *filteredIndexes = [data indexesOfObjectsPassingTest: ^(id obj, NSUInteger idx, BOOL *stop){return (BOOL)![obj hasPrefix:deleted];}]; NSArray *result = [[data objectsAtIndexes:filteredIndexes] sortedArrayUsingComparator: ^(id l,id r){ NSNumber *lLength = [NSNumber numberWithUnsignedInteger:[l length]]; NSNumber *rLength = [NSNumber numberWithUnsignedInteger:[r length]]; return [lLength compare:rLength]; }]; Objective-C $data = 'Apple', 'Microsoft', Google', 'Oracle', 'Dell' $deleted = 'O' $result = $data | ?{$_ -notlike "$deleted*"} | Sort-Object Length Powershell
  28. 28. 高階関数(C++) vector<string> data = { "Apple", "Microsoft", "Google", "Oracle", "Dell" }; auto deleted = 'O'; auto newEnd = remove_if(data.begin(), data.end(), [&](auto s) { return s[0] == deleted; }); data.erase(newEnd, data.end()); sort(data.begin(), data.end(), [](auto l, auto r) { return l.size() < r.size(); }); 28 • C++では
  29. 29. ライブラリ 利用者の自 由を縛る言語 利用者に自由 を与える言語 29
  30. 30. 標準C++ライブラリ 入出力 文字列 string 正規表 現 数値処理 複素数 分数 言語支援 例外 一般 時間 スマート ポインタ STL(Standart Template Libraly) コンテナ イテレー タ アルゴリ ズム 30
  31. 31. 標準C++ライブラリ(スマートポインタ) • ガベージコレクタをライブラリのみで導入 31 shared_ptr<ofstream> getStream() { return make_shared<ofstream>("C:test.txt"); }
  32. 32. 標準C++ライブラリ(chrono) • 時間を扱う機能 • ユーザー定義リテラルを活用 32 auto time = 5h + 30min + 15s; auto seconds = time.count();
  33. 33. 標準C++ライブラリ(入出力) • 入出力 • いろいろな機能がある • C#のToStringのようにクラスごとに出力形式 を定義することも可能 33 //768を右詰で8文字以内で16進数で表示 cout << hex << setw(8) << right << 768 << endl; cout << "定数:" << 3 << endl;
  34. 34. 標準C++ライブラリ(std:string) • 文字列クラス – 普通に多機能です – C文字列との相性もばっちり 34 string s = "ABC"; s = s + "DEF"; s.replace(2, 2, "XYZ"); int si = s.size(); const char* c = s.c_str();
  35. 35. 標準C++ライブラリ(コンテナ) • std::vector – 配列の代わりに利用できる • std::map – 連想配列 35 vector<int> v = { 1, 2, 3 }; v.push_back(4); int i = v[2]; map<string, double> m; m["A"] = 1.3; m["B"] = 2.5;
  36. 36. 標準C++ライブラリ(アルゴリズム) • さまざまなアルゴリズムが可能 – 自作を含めあらゆるクラスのあらゆるコンテナに 使用可 – ダックタイピング 36 vector<string> v = { "red", "blue", "green" }; deque<int> l = { 3, 5, 4 }; sort(v.begin(), v.end(), greater<string>()); sort(l.begin(), l.end(), greater<int>());
  37. 37. 標準C++ライブラリ(正規表現) • 正規表現も普通に使えます 37 regex isCsvRow("^d*(,d*)*$"); string row = "123,456,789"; smatch subMatchs; if (regex_match(row, subMatchs, isCsvRow)) { }
  38. 38. Boost C++のオープンソースライブラリ C++の標準化委員によって設立 標準C++ライブラリに採用されるものも きわめて先進的な機能 ヘッダのみで配布可能なものも多い 38
  39. 39. C++17 • 次のメジャーバージョンアップは2年後に迫っ ています。 – InfoQ Stroustrup氏の考えるC++17 - インタ ビューより • 全部実現したらさっきのコードはこのくらいに なるでしょう。 39 vector<string> data = { "Apple", "Microsoft", "Google", "Oracle", "Dell" }; auto deleted = 'O'; auto newEnd = data.remove_if([&](auto s) { return s[0] == deleted; }); data.erase(newEnd, data.end()); data.sort([](auto l, auto r) { return l.size() < r.size(); });
  40. 40. その他C++の利点 • Cの時代から互換性の維持 – 過去のどのような設計手法により書かれたプログ ラムも、動かなくなることがほぼない – 動作速度の互換性すら保証している(ゼロオー バーヘッドの原則) • すべてのパラダイムが平等に、どの組み合わ せでも使える 40
  41. 41. C++でできること Cのほぼすべての機能 オブジェクト指向 ジェネリックプログラミング • 高階関数 • 型推論 関数型プログラミング その他先進的な機能 41
  42. 42. ではC++に何ができないか • 機能が多すぎる!! – こんなイメージ 42
  43. 43. 機能が多すぎる弊害 覚えることが多い JavaとかC#の数倍はある まあこれは覚えればいいだ けなので大したことはない 43
  44. 44. 機能が多すぎる弊害 • 可読性が悪くなる 44 C C++ C# - - - STRUCT_A a; STRUCT_A *a = malloc(sizeof(STRUCT_A)); ClassA a; ClassA *a = new ClassA; shared_ptr<ClassA> a = make_shared<ClassA>(); ClassA a = new ClassA();
  45. 45. 機能が多すぎる弊害 すべての機能がすべて の組み合わせで使える 組み合わせ 爆発 全部試してみ ないと最適な ものがわから ない 45
  46. 46. まとめ • C++は低級なプログラミングもできますが、 JavaやC#と同じように高級なプログラミング もできます。 • 低級な記述もできてしまうため、意識的に高 級なプログラミングをする必要があります。 • だから、むしろJavaやC#に慣れている人の ほうが向いている面があります。 46

×