C++のお勉強(1)
- やりたいこと
- 教科書
- 環境構築
- ビルド方法(単体)
- ビルド方法(複数)
- デバッグツール
- ポインタ
- スマートポインタ
- 継承
- 参照引数の関数
- 関数の引数の種類
- テンプレート
- イテレータ
- 別名
- キャスト
- ビット演算
- 列挙型
- 静的変数
- 名前空間
- コンテナ
- 例外
やりたいこと
教科書
本を書きました。『基礎からしっかり学ぶC++の教科書』 | 配電盤
環境構築
$ sudo apt-get install g++
ビルド方法(単体)
$ g++ Sample.cpp
or
makefileを以下のように記載し、$ make
Sample: Sample.cpp g++ -o Sample Sample.cpp ##g++ -std=c++11 -o Sample Sample.cpp
ビルド方法(複数)
$ g++ -c Sample1.cpp -o Sample1.o $ g++ -c Sample2.cpp -o Sample2.o $ g++ Sample1.o Sample2.o
or
Sample: Sample1.o Sample2.o gcc -o Sample Sample1.o Sample2.o Sample1.o: Sample1.cpp gcc -c Sample1.cpp Sample2.o: Sample2.cpp gcc -c Sample2.cpp
参考:
デバッグツール
gdbの使い方
- ビルド時に-gをつけて実行
$ g++ -g -O0 Sample.cpp
- gdb立ち上げ
$ gdb a.out
- 使ってみる:ステップ実行
$ break main $ run $ next $ next ... $ quit
参考: gcc+gdbによるプログラムのデバッグ 第1回 ステップ実行、変数の操作、ブレークポイント
ポインタ
Sample1
#include <iostream> #include <string> using namespace std; class Robot{ string name; public: Robot(){} Robot(string n):name(n){} void SetName(string n){ name = n; } void Speak() const; }; void Robot::Speak() const { cout << "My name is " << name << "!" <<endl; } int main (){ Robot dora; Robot *p2; p2 = &dora; cout << p2 << endl; p2->SetName("Atom"); //(*p2).SetName("Atom"); p2->Speak(); //(*p2).Speak(); Robot *x; x = new Robot; x -> SetName("Tetsujin"); x -> Speak(); delete x; Robot *y; y = new Robot("Chappy"); y -> Speak(); delete y; int i; int num; string temp; Robot *r; cout << "Please a number of Robot you want to make."<<endl; cin >> num; r = new Robot[num]; for (i =0 ; i<num;i++){ cout << "Please type robot's name." <<endl; cin >> temp; r[i].SetName(temp); } for (i=0;i<num;i++){ r[i].Speak(); } delete [] r; }
Sample2
#include <iostream> using namespace std; int main(){ int x = 1; int* px = &x; int** ppx = &px; *px = 10; cout << x <<endl; cout << **ppx <<endl; }
↓
10 10
スマートポインタ
メモリリークを自動的に防いでくれる
#include <iostream> #include <complex> #include <memory> using namespace std; int main(){ using cpdb = complex<double>; shared_ptr<cpdb> x = make_shared<cpdb>(); cout << *x << endl; shared_ptr<cpdb> y = make_shared<cpdb>(1.1,2); cout << *y << endl; shared_ptr<cpdb> z = make_shared<cpdb>(*y); cout << *z << endl; }
継承
#include <iostream> using namespace std; class Robot { string name; public: void SetName(string n){name = n;} string GetName() const{ return name;} void InputData(); void ShowData() const; }; void Robot::InputData(){ cout << "input Name:"; cin >> name; } void Robot::ShowData() const{ cout << "name:"<<name<<endl; } class FRobot : public Robot { int power; public: void SetPower(int p){ power = p;} int GetPower() const{ return power;} void InputData(); void ShowData() const; int FullPower() const { return power * 10;} }; void FRobot::InputData(){ Robot::InputData(); cout << "input power:"<<endl; cin >> power; } void FRobot::ShowData() const{ Robot::ShowData(); cout << "FullPower is :" << FullPower() << "!!!" << endl; } int main() { FRobot f[3]; string temp; int i,sum; for (i=0;i<3;i++){ f[i].InputData(); } cout << endl; cout << "display all robot power" << endl; for(i = 0; i< 3; i++){ cout <<"Mark" <<i + 1 << "!"<<endl; f[i].ShowData(); cout << "----------------" <<endl; } sum = 0; for (i = 0 ; i <3 ; i++){ sum += f[i].FullPower(); } cout << "ALL ROBOT FULL POWER :" << sum <<"!!!"<<endl; }
参照引数の関数
参照引数の場合、引数にコピーしないため軽量
void func(X& a){...} or void func(const X& a)
上は、引数のデータが書き換わる可能性あり
下は、書き換わることを防ぐ
関数の引数の種類
- int → void func1 (int x) {}
- const int → void func2 (const int x) {}
- int& → void func3 (int& x) {}
- const int& → void func4 (const int& x) {}
- int&& → void func5 (int&& x) {}
- const int&& → void func6 (const int&& x) {}
- int → void func7 (int x) {}
- const int → void func8 (const int x) {}
これだけ考えられるが基本的にはfunc1~4を考えれば良い。
参考:右辺値参照・ムーブセマンティクス - cpprefjp C++日本語リファレンス
テンプレート
include <iostream> #include <string> using namespace std; template <typename T> void SwitchValue(T& x, T& y){ T temp = x; x = y; y = temp; } int main(){ int a = 1; int b = 2; SwitchValue(a,b); cout << a << endl; cout << b << endl; string c = "1"; string d = "2"; SwitchValue(c,d); cout << c << endl; cout << d << endl; }
参考:第 4 章 テンプレート (C++ プログラミングガイド)
イテレータ
参考:C++ iterator 入門 C++ イテレータ入門 - プログラミングの教科書を置いておくところ
別名
using uint = unsigned int; //typedef unsigned int uint; uint x = 0; // equal unsigned int x = 0
キャスト
#include <iostream> using namespace std; int main(){ int x = 0; x = static_cast<int>(1.11); cout << x << endl; x = (int)1.11; cout << x << endl; x = int(1.11); cout << x << endl; }
ビット演算
#include <iostream> using namespace std; int main(){ int x = 1; int y = 5; cout << (y >> 1) << endl; //2 cout << (y << 1) << endl; //10 cout << (y >> 2) << endl; //1 cout << (y << 2) << endl; //20 cout << (x & y) << endl; //1 cout << (x | y) << endl; //5 cout << (x ^ y) << endl; //4 cout << (~x) << endl; //-2 }
列挙型
#include <iostream> using namespace std; int main(){ enum robots { Atom, Tetsujin, Dora }; robots x = Tetsujin; cout << (x==Tetsujin ? "Mark21": "Mark0")<<endl; }
静的変数
一度だけ初期化され、その後共有される
以下の例ではstaticがないと、出力は1,1,1になる
#include <iostream> using namespace std; int increment(){ static int x = 0; ++x; return x; } int main(){ cout << increment() <<endl; //1 cout << increment() <<endl; //2 cout << increment() <<endl; //3 }
名前空間
#include <iostream> using namespace std; int x; namespace NAME1{ int x = 1; } namespace NAME2{ int x = 2; } int main(){ int x = 3; cout << x << endl;//3 cout << ::x << endl;//0 cout << NAME1::x << endl;//1 cout << NAME2::x << endl;//2 }
コンテナ
#include <iostream> #include <complex> #include <vector> using namespace std; int main() { using cpdb = complex<double>; vector<int> v1; v1.push_back(2); v1.push_back(3); v1.push_back(4); v1.push_back(5); vector<int> v2(4); v2[0]=6; v2[1]=7; v2[2]=8; v2[3]=9; vector<int> v3{10,11,12,13}; for (int i = 0 ; i < v1.size() ;i++){ cout << v1[i] << endl; cout << v2[i] << endl; cout << v3[i] << endl; } v3.pop_back(); v3.erase(v3.begin() + 1); for (int i = 0 ; i < v3.size() ;i++){ cout << v3[i] << endl; } vector<int> v4(v1); for (int i = 0 ; i < v4.size() ;i++){ cout << v4[i] << endl; } vector<cpdb> v5; v5.reserve(10); v5.emplace_back(1.11,2.0); cout << v5.capacity() << endl; vector<vector<int>> v6{{1,2,3},{4,5,6}}; cout << v6.size() <<endl; cout << v6[0].size() <<endl; cout << v6[0][2] << endl; }
例外
#include <iostream> using namespace std; void DoSomething(){ throw runtime_error("error!"); } int main(){ try{ DoSomething(); } catch (exception& e){ cerr << e.what() <<endl; } cout << "Normal Stop."; }