Last-modified: 2016-03-28 (月) 19:36:57
C++/チートシート

はじめに

実装依存(vc,clang,gcc,...)や、規格依存(C++03,C++11,C++14,...)、外部ライブラリ依存(boost,...)などの場合でも、基本的に注釈はいれません(察してください)
cppかつstdのみ常にusing namespaceしています。

入出力

C++出力フォーマット

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 
 
 
 
 
-
-
!
|
-
!
|
-
!
|
|
|
|
|
!
#include <iostream>
#include <iomanip>
 
using namespace std;
 
int main()
{
    // hex(16進), dec(10進数), oct(8進数), showbase(16/8進数にプレフィックスを付加),noshowbase いずれも持続性あり
    cout << showbase << hex << 200 << "\n";
 
    // fixed(固定小数点表現), scientific(仮数、指数表現), setprecision(精度) いずれも持続性あり
    cout  << setprecision(5) << scientific << 123.456 << "\n";
 
    // setw(幅を揃える) 持続性なし、指定より長い値はすべて表示される
    cout
            << '|' << setw(10) << 12345 
            << '|' << setw(5) << 9876543210 
            << '|' << "\n";
 
    return 0;
}

文字列

文字列から数値へ変換

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 
 
 
 
 
-
|
|
|
-
!
!
#include <iostream>
 
using namespace std;
 
int main()
{
    istringstream is("123.456");
    double d = 0.0;
    is >> d;
    // if (!is)でエラーを検出可能
    return 0;
}

数値から文字列へ変換

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 
 
 
 
 
-
|
|
|
!
#include <string>
 
using namespace std;
 
int main()
{
    const string s(to_string(12.3456));
    cout << s << "\n";
    return 0;
}

コンテナ

重複のないランダムな集合を作成

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 
 
 
 
 
 
-
-
!
|
|
|
|
|
|
!
#include <iostream>
#include <algorithm>
 
using namespace std;
 
int main()
{
    // 初項0,公差1の等差数列を、メルセンヌ・ツイスタでシャッフルして生成
    vector<int> src(1024 * 1024);
    iota(src.begin(), src.end(), 0);
    random_device rd;
    shuffle(src.begin(), src.end(), mt19937(rd()));
    
    for (const auto& i : src) { cout << i << "\n"; }
    return 0;
}

複数のキーを持つmultimapの範囲検索

Everything is expanded.Everything is shortened.
  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
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 
 
 
 
 
 
 
 
 
 
 
-
|
-
|
!
|
-
|
!
!
 
 
-
-
|
|
|
|
!
|
|
|
-
|
!
|
|
-
|
|
-
|
!
!
|
|
-
|
|
-
|
!
!
|
|
!
#include <iostream>
#include <map>
#include <algorithm>
#include <stdio.h>
 
using namespace std;
 
typedef pair<char, int> key;
typedef multimap<key, string> bar;
 
struct FindFirstKey
{
    bool operator()(const pair<key, string>& lhs, const char& rhs) const
    {
        return (lhs.first.first < rhs);
    }
    bool operator()(const char& lhs, const pair<key, string>& rhs) const
    {
        return (lhs < rhs.first.first);
    }
};
 
int main()
{
    const bar b = {
        {key(5,20), "aaa"},
        {key(100,20), "bbb"},
        {key(5,10), "ccc"},
        {key(5,20), "ddd"}
    };
    
    printf("--- all ---\n");
    for (const auto& v : b)
    {
        printf("%03d:%03d\t%s\n", v.first.first, v.first.second, v.second.c_str());
    }
      
    printf("--- find(key) ---\n");
    {
        const auto bound = b.equal_range(key(5,20));
        for (auto it = bound.first; it != bound.second; ++it)
        {
            printf("%03d:%03d\t%s\n", it->first.first, it->first.second, it->second.c_str());
        }
    }
    
    printf("--- find(key.first) ---\n");
    {
        const auto bound = equal_range(b.begin(), b.end(), 5, FindFirstKey());
        for (auto it = bound.first; it != bound.second; ++it)
        {
            printf("%03d:%03d\t%s\n", it->first.first, it->first.second, it->second.c_str());
        }
    }
 
    return 0;
}

イテレータの要素番号を取得

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 
 
 
 
 
 
 
-
|
|
|
|
|
!
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
int main()
{
    vector<int> src(1024);
    iota(src.begin(), src.end(), 0);
    const auto it = find(src.cbegin(), src.cend(), 632);
    cout << distance(src.cbegin(), it) << "\n";    
    return 0;
}

イテレータからリバースイテレータを取得

Everything is expanded.Everything is shortened.
  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
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 
 
 
 
 
-
|
|
|
|
-
|
!
|
|
|
-
|
!
|
-
!
-
|
!
|
-
!
-
|
!
|
|
|
!
#include <iostream>
#include <vector>
 
using namespace std;
 
int main()
{
    const int tv[] = { 1,2,3,4,5,6,7,8 };
    vector<int> v(&tv[0], &tv[0]+sizeof(tv)/sizeof(tv[0]));
    
    for (vector<int>::const_iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << *it << "\n";
    }
    cout << "-----------\n";
    
    for (vector<int>::const_reverse_iterator it = v.rbegin(); it != v.rend(); ++it)
    {
        cout << *it << "\n";
    }
    cout << "-----------\n";
    // コンストラクタで生成
    for (vector<int>::const_reverse_iterator it(v.end()); it != v.rend(); ++it)
    {
        cout << *it << "\n";
    }
    cout << "-----------\n";
    // std::reverse_iteratorで生成
    for (reverse_iterator<vector<int>::const_iterator> it(v.end()); it != v.rend(); ++it)
    {
        cout << *it << "\n";
    }
    cout << "-----------\n";
    
    return 0;
}

イテレータ、リバースイテレータ変換の注意

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 
 
 
 
 
 
-
|
|
|
|
|
-
|
!
|
|
|
|
!
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
int main()
{
    const vector<int> v = {1,2,3};
    const vector<int>::const_iterator it = find(v.begin(), v.end(), 2);
    const vector<int>::const_reverse_iterator itr(it);
    const vector<int>::const_iterator it2 = itr.base();
    
    // 変換すると同じものを指さない
    // rend, 1(begin), 2, 3(rbegin), end
    cout << *it << "\n";    // 2
    cout << *itr << "\n";   // 1
    cout << *it2 << "\n";   // 2
    
    return 0;
}

継承

private継承

親クラスのpublicなリソースに外からアクセス出来なくなる
アップキャストも出来ない

Everything is expanded.Everything is shortened.
  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
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 
 
 
 
 
-
|
|
|
|
|
!
 
 
 
-
|
|
|
|
-
|
|
|
!
!
 
 
-
|
-
|
|
|
!
!
#include <iostream>
 
using namespace std;
 
class foo
{
public:
    foo():m_i() { cout << __FUNCTION__ << "\n"; }
    virtual ~foo() { cout << __FUNCTION__ << "\n"; }
    void f() { cout << __FUNCTION__ << "\n"; }
    int m_i;
};
 
class bar
    : private foo
{
public:
    bar() { cout << __FUNCTION__ << "\n"; }
    virtual ~bar() { cout << __FUNCTION__ << "\n"; }
    void f1()
    {
        cout << "bar::f1, start..." << "\n";
        foo::f();
        cout << "bar::f1, finished!!" << "\n";
    }
};
 
int main()
{
    bar b;
    // 以下全てコンパイルエラー
    //b.f();
    //b.m_i = 10;
    //static_cast<foo*>(&b)->f();
    return 0;
}

クラス設計

明示的なコピー/代入不可

Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
-
!
-
|
|
|
|
|
|
|
!
 
-
!
-
|
|
|
!
// C++11 deleteで明示的にも行える
class foo
{
public:
    foo(){}
    virtual ~foo(){}
    foo(const foo&) = delete;
    foo& operator =(const foo&) = delete;
    foo(const foo&&) = delete;
    foo& operator =(const foo&&) = delete;
};
 
// C++03 private宣言する
class foo
{
private:
    foo(const foo&);
    foo& operator =(const foo&);
};

その他

処理時間を計測する

Everything is expanded.Everything is shortened.
  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
 26
 27
 28
 29
 30
 31
 32
 33
 
 
 
-
-
|
|
!
-
|
|
|
|
|
|
|
-
|
|
|
|
|
!
!
!
 
 
-
|
-
!
|
!
#include <stdio.h>
#include <chrono>
 
namespace{
    // 解像度の高いclock
    // VS2015以降なら、high_resolution_clockで同等の結果が得られる
    // VS2013のhigh_resolution_clockは、QueryPerformanceCounterを使っていないので実装している
    struct nanoclock
    {
        typedef long long rep;
        typedef std::nano period;
        typedef std::chrono::duration<rep, period> duration;
        typedef std::chrono::time_point<nanoclock> time_point;
        static const bool is_steady = true;
 
        static time_point now()
        {
            LARGE_INTEGER frequency;
            ::QueryPerformanceFrequency(&frequency);
            LARGE_INTEGER count;
            ::QueryPerformanceCounter(&count);
            return time_point(duration(static_cast<rep>(count.QuadPart) * (static_cast<rep>(period::den) / static_cast<rep>(frequency.QuadPart))));
        }
    };
};
 
int main()
{
    const auto start = nanoclock::now();
    // 処理...
    const auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(nanoclock::now() - start).count();
    printf("time=%lld nanosec", duration );
}