検索のしづらいC++の記号の意味をまとめてみました。C++11、C++14をはじめとして網羅的に集めたつもりです。
C言語についての記述もありますが、共通した記号であってもC++とCでは文法や動作の子細が異なる場合がありそのまま適用できないことがあります。また掲載してある記法は説明のために載せているのであってすべてが推奨できるわけではないことにご注意ください。用語や分類、解説はかなりいい加減です。
型[要素数] | 配列型(要素数は定数でなければならない。要素数を省略した型は不完全型)。
typedef int array[5]; //配列型int[5]にarrayという名前を付ける。 void f(int ptr[]); //関数の宣言に用いてvoid f(int* ptr);と同じ void f(int ptr[5]); //この場合要素数の記述は無意味で上記と同じ。 //動的配列の確保(まずはstd::vectorを検討したほうがよい) auto r = boost::make_shared<int[]>(5); //値初期化される | |
new 型[要素数] | 配列版のnew演算子。動的配列を確保する(要素数が定数である必要はない。また0も指定できる)。注意点は下記の delete [] を参照。
//動的配列の確保(まずはstd::vectorを検討したほうがよい) //値初期化するには後ろに()や初期化リストの{}を付ける std::unique_ptr<int[]> p( new int[5]() ); boost::shared_ptr<int[]> q( new int[5]{0,1,2,3,4} ); //スマートポインタのテンプレートパラメータにはint[]のように //同じく配列型を指定する | |
型 名前[要素数] | 固定長配列の宣言(要素数は定数でなければならない。推測可能な場合に省略可)。 std::arrayクラスの方がより扱いやすい。C99ではローカル変数の配列長を動的に指定できる。またgcc拡張、VC拡張、C99では構造体の最後に長さ0の配列を宣言でき可変長の構造体を宣言できる。
int name[4][3]; //3x4の二次元配列 (値初期化する場合は{}か={}を使う) //最終次元の2は省略して初期化リストから推測させる int name[][3] = {{},{}}; //3x2の二次元配列 char moji[] = "yes"; //char配列が yes\0 で初期化され要素数は4となる //配列型は暗黙のうちにその先頭要素へのポインタへ変換されるため注意 char* p = moji; assert(*p == 'y'); struct s { int length; char data[]; //C99の可変長配列メンバ }; | |
[引数] | 添え字演算子。0から始まる配列要素へのアクセス。std::vectorやstd::array等でもオーバーロードされ使用できるが境界チェックのあるat()メンバ関数の方がおすすめ。regexのmatch_resultsではマッチした表現に対応するsub_matchを返す([0]はマッチした全体、[1]以降がキャプチャ部分)。boost.spirit、xpressiveにおいて[]はsemantic action等を記述するために用いられる。C++20のchronoでは第何曜日を表す Sunday[2] //第2日曜日。C++23から,で区切って複数の引数を取れるようになる。
int v = p[3][4]; //二次元配列の3行4列目の値をvに代入 char x = "abcdefg"[3]; //xには'd'が代入される | |
map系コンテナ変数[キー] | std::map系コンテナにおける添え字のオーバーロード。要素へのアクセスだがコンテナにこのキーが存在しないとキーが新たに挿入されて要素が構築される。at()メンバ関数のほうが通常の配列の添え字[]に近い。
std::unordered_map<std::string, std::string> week_dictionary; week_dictionary["Sunday"] = "日曜日"; week_dictionary["Monday"]; assert(week_dictionary.size() == 2); | |
整数[配列変数] | 配列要素へのアクセス。トリッキーな書き方。配列変数[整数]の表記と同じ。
int v = 2[p]; // int v = p[2];に同じ int v = *(p+2); //これも同じ | |
delete [] | 配列版delete演算子。動的配列の解放。new T[]とセットで使う。new Tにはdelete P を使用し、new T[]にはdelete [] Pを使用しなければならない。しかしながら様々な安全上の理由からスマートポインタを使う方が良い。そもそも動的配列ならばstd::vectorがおすすめ。
//動的配列の確保と解放(極めて問題が発生しやすい。 // まずはstd::vectorを検討したほうがよい) auto* p = new int[5]; //値初期化されない delete [] p; | |
[[属性]] | 属性を指定する。もしくは将来のC++においてコントラクトを表し事前事後条件などを指定できるようになるかも。「,」で区切ると複数の属性を指定できる。属性のトークンには ::、()、[]、{}が現れる。C++17よりusing 属性名前空間: で表記の省略ができる
//この関数の使用は推奨されない [[deprecated("too old")]] void SomeFunction(int x, int y); [[using gcc: pure, cold]] int func(); //[[gcc::pure, gcc::cold]]と同じ [[assume(x > 0)]]; //C++23 xが正であることを仮定して良いとコンパイラに伝える。最適化用 void f(int x) [[expects: x > 2]]; //(もしかしたら将来のC++において)引数が2以下の場合既定でプログラムが終了 | |
auto 略[名前, 名前] | 右辺の構造体から個別のメンバを受け取り新しい変数を宣言する(構造化束縛)。std::tieをより簡単にしたもの。(C++17)
std::map<T,U> m; auto const [ pos, done ] = m.insert(v); // insert()の戻り値 std::pair<iterator,bool>を受け取り // std:map::iterator const pos = ...; // bool const done = ...; の2変数が宣言される if(done) { } | |
[キャプチャリスト]略(仮引数リスト) mutable ->戻り値型 { いろいろ } | ラムダ式(即席の関数オブジェクト)。キャプチャリストと(仮引数リスト)とmutableは不要な場合に省略可。->戻り値型は場合により省略可。キャプチャリストにはthisや後述の&や=が現れる。C++17では*thisがクラス自体のコピーに使える。キャプチャした変数の寿命には注意が必要。C++20では<>で通常のテンプレート関数のようにパラメータリストを指定可能になる予定。
//int値を引数に取り3を足して返すラムダ式 の変数fを宣言 auto f = [](int a) { return a + 3; }; assert( f(2) == 5 ); // f()でラムダ式を呼び出す [](){}(); //何もしないラムダ式を作り、最後の()でこれを呼び出す []<class T>(T a){}; //C++20 | |
auto 関数名(仮引数リスト) -> 戻り値型 | 戻り値型を後ろに記述する関数宣言。C++14なら「-> 戻り値型」は型が推論可能な場合は省略可。「関数名」の部分が「(*名前)」だと関数ポインタ型を表す。「関数名」の部分が「(&名前)」だと関数への参照型を表す。「名前」の部分は場合により省略可。
auto func(void) noexcept -> int { return 0; } | |
template <略> クラス名(仮引数リスト) -> そのクラスの具体的な型; | 推論ガイド。テンプレートクラスのテンプレート引数をコンストラクタから推論する際に複雑な推論を可能にするためのもの。簡単に推論可能な場合は特に必要ない。(C++17)
//template <class T> struct LockGuard { // tempate <class ...Args> LockGuard(Args... args){ /**/ } //}; template <class ...Args> LockGuard(Args...) -> LockGuard<std::common_type_t<Args...>>; //LockGuard<decltype(lock1),decltype(lock2)> g(lock1, lock2);//これが LockGuard g(lock1, lock2); //こう書ける | |
requires (引数リスト){式 や 型; } | Conceptsのrequires式(C++20)。{}内の式や型が有効であることを要求する。有効であればrequires式はbool値としてtrueをそうでなければfalseを返す。要件の式や型は複数含めることができ、下記の複合要件も使用できる。(引数リスト)は不要であれば省略可。
// ある型Tにはiteratorという内部の型が必要なことを // 表すコンセプトCを定義 template <class T> concept C = requires (T t) { typename T::iterator; }; | |
constexpr {式} noexcept -> 制約; | 上記requires式中の複合要件。{式}は中の式が有効であることを要求する。「->制約」は式がこの制約を満たすことを要求する。「constexpr」は「式」がconstexprであることを要求する。noexceptは「式」がnoexceptであることを要求する。「->制約」「constexpr」「noexcept」はそれぞれ要求しない場合は不要。
// ある型Tを*で間接参照することができ、その間接参照した型が // intへ変換可能である必要があることを表すコンセプトCを定義 template <class T> concept C = requires (T t) { {*t} -> std::convertible_to<int>; }; | |
クラスへのポインタ変数 -> メンバ | アロー演算子。ポインタを経由してのメンバ関数やメンバ変数へのアクセス。下記のドット演算子と間接演算子を用いた「(*クラスへのポインタ変数).メンバ」の表記に普通は等しい。
std::unique_ptr<std::string> p(new std::string()); p->append("hello"); //xがテンプレート仮引数でそのテンプレートメンバ関数funcを使う場合 x->template func<int>(); //templateを途中に挟み文法の曖昧さを解決 | |
クラス変数 . メンバ | ドット演算子。メンバ関数やメンバ変数へのアクセス。
std::pair<bool, int> p,q; p.first = true; //pのメンバ変数firstにtrueを代入 p.swap(q); //pのメンバ関数swapを呼び出す。その際の引数はq x.template func<int>(); //上記アロー演算子の例を参照のこと。 | |
. | 小数点。後述の「小数点を含む数値」項目も参照。
9.8 .5 // 0.5 -6. // -6.0 .7E+2f // 0.7 × 10の+2乗 のfloat型 つまり 70.0f | |
{ .メンバ変数 = 値, .メンバ変数 = 値 } | C99(C++20で導入予定だがC99より制約がある)の機能で構造体のメンバ名を指定して初期化できる(designated initializer)。[]を用いると配列を初期化する場合にその要素位置を指定できる。gcc拡張では member:val も同じ意味で使え、[index] val や [index] = val で指定した位置の要素を初期化でき、その位置も [from ... to] として範囲で指定できる 。
type identifer[5] = { [要素位置].メンバ変数 = 値 };
| |
クラス変数 .* メンバポインタ | メンバポインタを使用した直接のメンバアクセス。メンバ関数を呼び出す場合は (クラス変数.*メンバポインタ)(実引数)のように()で括る必要がある。 | |
クラス変数へのポインタ ->* メンバポインタ | メンバポインタを使用したポインタ経由のメンバアクセス。メンバ関数を呼び出す場合は (クラス変数へのポインタ->*メンバポインタ)(実引数)のように()で括る必要がある。 | |
変数型 クラス名 ::* 名前 | 「名前」を省略した形が クラスのメンバ変数へのポインタ型(メンバ変数ポインタ型)を表す。「名前」を付ければその変数の宣言。typedefで使えば「名前」はその型の別名となる。 | |
戻り値型 (クラス名 ::*名前)(仮引数リスト) | 「名前」を省略した形が クラスのメンバ関数へのポインタ型(メンバ関数ポインタ型)を表す。「名前」を付ければその変数の宣言。typedefで使えば「名前」はその型の別名となる。
struct s { void func(); }; void (s::*identifer)() = &s::func; s obj; (obj.*identifer)();// 上記の .* を使用してメンバ関数呼び出し | |
... | C言語由来の可変長引数。型安全ではないため注意を要する。呼び出すときに小さい型はint/unsigned intへ、floatはdoubleへ変換される。オーバーロード解決の際の優先度は最低である。
int printf(const char* format, ...); int printf(const char* format...); //上に同じ( ,は必要ない) | |
... | 関数風マクロの可変長引数。
// 引数は__VA_ARGS__で展開する #define MACRO_F(...) func(__VA_ARGS__); // MACRO_F(1,"a") と書くと func(1,"a") に展開される | |
... | 可変長テンプレート、またはそのパラメータパックの展開、C++17において()と特定の演算子と共に用いてfold式を表す。
f(1, 2.0); //こう呼び出すと template <class... T> //Tは可変長テンプレート void f(T... args) // argsはTのパラメータパックでint型の1, double型の2.0を含む { g(args...); // パラメータパックを展開してg(1, 2.0);と呼び出す h(std::to_string(args)...); //こんな展開も可能 //h(std::to_string(1), std::to_string(2.0));に同じ typedef boost::mpl::vector<T...> type; // <int, double>と展開 ( ... + args); // ((1) + 2.0) と左から畳み込むfold式 (args + ... + 3); // (1 + (2.0 + 3)) 初期値に3を指定して右から //ラムダ式のキャプチャリストで可変長の宣言ができる(C++20) [...xs = args]{}; } //ラムダ式の可変長テンプレート (C++14のgeneric lambda) [](auto... a){}; //C++20ではテンプレート関数をラムダ式と同じ簡略表記で書ける void k(auto... a){}; //(C++20)コンセプトCを...と以下のように組み合わせると template <C<short>... T> struct S{}; // requires C<T1,short> && C<T2,short> && ... のように制約が掛かる template <class...T> void j(T......) {} //可変長テンプレートとC言語由来の可変長引数を組み合わせた形 //前のT...が可変長テンプレートで後の...がC言語由来の可変長引数 void j(T... , ...) {} //これと同じ template <typename... Bases> class Derived : Bases... { //多重継承できる using Bases::Func...; //複数の派生元に共通の関数をusing宣言できる(C++17) }; | |
sizeof...(可変長テンプレート) | 可変長テンプレートパラメータまたはそのパラメータパックの要素数取得 | |
case 定数 ... 定数: | gcc拡張でcaseラベルに該当する値を範囲で指定できる。 | |
catch(...) { } | すべての例外を捕捉するcatchブロック。 | |
importもしくはmodule モジュール.サブモジュール | C++20のモジュールの宣言 「.」は実際には名前の一部。 | |
importもしくはmodule 略 : パーティション; | C++20のモジュールパーティションの宣言 | |
:: | スコープ解決演算子。スコープを修飾して曖昧さを解決する。属性名前空間を指定する。staticメンバ変数の定義。クラスのインスタンスを作らずにstaticメンバへのアクセス。ADLの回避。仮想関数呼び出しの回避。C++17よりネストしたnamespaceをまとめて記述することにも使える。
::func(); //グローバル名前空間のfuncを呼び出し std::find(); //std名前空間のfindを呼び出し struct S { static int n; //staticメンバ変数なのでこの宣言は定義ではない // 注 C++17からinlineをつけると定義にできる static S Foo() { return S(); } int Bar() [[gcc::cold]]; //属性名前空間 typedef float value_type; }; int S::n; //これがstaticメンバ変数の定義 int S::Bar() { //メンバ関数を分離して定義 //昔のCfrontでは::の代わりに.が用いられていたとのこと return 0; } //Sクラス内部のtypedefされた型value_typeを用いて変数aを宣言 S::value_type a = 0.0f; //float a=0.0f; struct T : S { using S::S; //using declarationを用いた継承コンストラクタ }; using namespace std::tr1; //using directive void f() { S::n = 1; //staticメンバ変数へのアクセス auto v = S::Foo(); //staticメンバ関数の呼び出し } namespace a::b::c { } //namespace a { namespace b { namespace c { }}}と同じ | |
; | (セミコロン)文の終わり。for文の区切り(ループ条件を省略すると常に真と評価される)。C++17よりswitchもしくはif(変数の宣言; 条件式)とすることでswitch,if,else節内にスコープを限定した変数の宣言ができるようになり、C++20よりrange-based for文でも利用できるようになる。
//for(変数の宣言; ループ条件; 毎ループ後に評価される式) for (;;) {} //無限ループ if (auto a=x; a.val > 0) {} //C++17より int i; // int 型の変数iを定義。組み込み型なので値は不定値 auto int i; //ローカル変数を表す昔の記述法 class a; //クラスaの前方宣言。struct、unionも。 struct s o; //構造体s型の変数oを定義。Cの文法。 s o; //上と同じ。 int f(); //関数fの前方宣言(プロトタイプ宣言) 1+1; //式1+1を評価。この例の場合、副作用もなく //結果も利用していないので特に意味はない throw; //catchされた例外の再送出 | |
for(要素変数の宣言 : 範囲) | (コロン) 範囲for文の区切り。C++20よりfor(変数の宣言 ; 要素変数の宣言 : 範囲)が使えるようになる。
int range[] = {1, 2, 3}; for (auto val : range) cout << "#" << val; //出力 #1#2#3 for (auto obj = func(); auto val : obj.getrange()) {} //C++20 | |
式1 ? 式2 : 式3 | 条件演算子(三項演算子)。まず式1が評価されtrueならば式2が評価され、falseなら式3が評価されて最終的な結果となる。式2と式3は同じ型(暗黙的に変換できればOKもしくはthrow)である必要がある。C言語では?:の優先順位は代入演算子=よりも高いがC++においては同じであることに注意。
std::string greeting = (english) ? "Hello" : "こんにちは"; | |
式1 ?: 式3 | gcc拡張で条件演算子の真ん中の式を省略できる。式1 ? 式1 : 式3 に等しい。ただし式1が評価されるのは一度のみ。 | |
ラベル名: | ラベル。switch文のcase ラベル: や default:。gotoのジャンプ先。これらのジャンプ箇所において変数の初期化処理を飛び越えないように注意すること。 | |
_Generic(式, 型:式, 略) | C++ではなくC11のgeneric selection。最初の式の型に対応する式を予め”型:式”の形で列挙しておきコンパイル時に選択できる。これを利用してC++のオーバーロードライクなこと等が可能。 | |
アクセス指定: | アクセス指定 public: protected: private: の三種 。structのメンバはデフォルトでpublic:指定、classのメンバはデフォルトでprivate:指定されている。クラス継承のアクセス指定については下記「派生クラスの定義」の項を参照。 | |
整数型 変数名: ビット数 |
ビットフィールド
struct s { unsigned flag : 2; unsigned :0; //ゼロ幅を指定すると前後のメモリアドレスを分割できる //よってflagとoptはアドレスが別になる unsigned opt: 3, done: 1; unsigned a : 5 = 0; //C++20から初期子が使える }; | |
コンストラクタ: メンバ変数名やクラス名(), メンバ変数名やクラス名() { } | コンストラクタのメンバ初期化リスト。メンバ変数や基底クラスを初期化できる。また「自身のクラス名(実引数リスト)」となっている場合は委譲コンストラクタ呼び出し。()の代わりに{}で直接リスト初期化もできる。初期化される順序はメンバの定義順でメンバ初期化リストで記述した順ではない。以下の例ではv1が最初に初期化される。また昔のCfrontでは基底クラス名を書かずに()だけで初期化できたとのこと。
struct s { s() : v2(0), v1(0) { //デフォルトコンストラクタ v1,v2を初期化 } s(const char* p) //const char*を引数に取るコンストラクタ : s() //(上で定義したものを)委譲コンストラクタとして呼び出し { cout << p; } int v1; int v2; s(double d) try : s() //関数tryブロックを組み合わせた形 { } catch (...) { } }; | |
classかstruct クラス名 : virtual アクセス指定 継承元クラス, virtual アクセス指定 継承元クラス { }; | 派生クラスの定義。アクセス指定やvirtualやクラス名は必要に応じて付ける。structはデフォルトでpublic継承、classはデフォルトでprivate継承される。
struct derived : public base { }; | |
enum classかstruct 名前 : 整数型 | enumの基底型を指定する。class、structはscoped enumにする場合。名前は不要な場合は省略可。
enum week : short int { Sunday, Monday, Tuesday, }; | |
* | (アスタリスク)乗算演算子。 ちなみにべき乗の演算子は標準には存在せず、代わりにstd::pow関数が利用できるが浮動小数点数での計算となることに注意。 assert( 3*5 == 15 ); | |
型名* | ポインタ型。常に参照先のオブジェクトの寿命に注意が必要。
int d = 0; //int型 //p は d へのアドレスを格納するポインタ型 int* p = &d; //q は p(int*型) へのアドレスを格納するポインタ型 int** q = &p; // d,p,qの変数自体のアドレスがそれぞれ100,112,116だとすると // pが格納している値は100、qが格納している値は112になる。 int v = 0; int* i = &v; auto x = i; // x は int* 型 auto* y = i; // y も int* 型 //autoだけでも良いが * を付けてポインタ型であることを明示してもよい //cv修飾子(constやvolatile)は*との位置関係によって修飾先が異なる int const * r = i; //rが指している先は変更できないがr自体は変更可 int * const t = i; //tが指している先は変更可、t自体は変更不可 r = nullptr; //OK t = nullptr; //ill-formed *r = 1; //ill-formed この*は下記の間接参照演算子 *t = 2; //OK この*は下記の間接参照演算子 | |
*ポインタ変数 | 間接参照演算子。ポインタ(イテレータ)の指す先を参照する。スマートポインタやboost.optionalでもオーバーロードされている。
//上記例の続き int val1 = *p; int val2 = **q;//ポインタqの指す先を参照し、さらにその先を参照する assert(val1 == val2); int* x; //これはポインタ型 { int localval; x = &localval; } *x = 1; //NG localvalは寿命切れで未定義動作 | |
戻り値型 (*名前)(引数リスト) | 戻り値型 (引数リスト)というシグネチャを持つ関数へのポインタ。関数ポインタ。場合により名前は省略可。 「名前」部分が名前(引数リスト)という形式の場合は「戻り値型 (引数リスト)という関数へのポインタ」を返す関数宣言となる。 // void (*)(int, int)という関数ポインタ型にnameという型名を付ける using name = void (*)(int,int); // usingを使用(新しく高機能) typedef void (*name)(int, int); // typedefを使用 //下記のように関数へのポインタ、配列への参照などを戻り値型にするときは //外側から挟むように記述するがusingやtypedefを用いたほうがわかりやすい void* (*(*func)(int, double*))(char*) = nullptr; //上は下と同じ using rettype = void*(*)(char*); //char*を引数にとりvoid*を返 // す関数ポインタ型にrettypeと別名をつける rettype (*func)(int, double*) = nullptr; //int,double*を引数に取 //りrettypeを返す関数ポインタfuncを宣言、定義しnullptrで初期化 | |
型名 (*名前)[整数] | 型名[整数]という配列へのポインタ。場合により名前は省略可。 「名前」部分が名前(引数リスト)という形式の場合は「型名[整数]という配列へのポインタ」を返す関数宣言となる。 | |
[ *this ] | C++17のラムダ式のthisコピーキャプチャ指定。
struct s { void f() { [*this](){ //sのメンバ変数自体をコピーキャプチャするラムダ式。 value = 1; //このvalueは元のvalueとは別物 }; [self = *this](){ self.value = 1; }; //C++14で上記例を実現する場合 [this](){}; //メンバ変数はコピーされずthisポインタを経由して参照される } int value = 0; }; | |
+ | 加算の二項演算子。正の符号を表す単項演算子。std::basic_stringにおいて文字列を連結する(その他のライブラリでも連結を表す演算子としてオーバーロードされていることがある)。浮動小数点数リテラルの指数の符号。
short val = 1+2; //val == 3 auto a = +val; //正の符号を表す単項演算子。 // + は - ほど意味を持たないが汎整数拡張が行われaはint型になる //キャプチャのないラムダ式は関数ポインタへ変換できるが // +を適用することで強制的に変換できる auto* fp = +[]{ return 1; }; auto str = std::string("hello") + " wolrd!"; // str == "hello world!"; 1.5e+2; // 1.5 掛ける 10の +2乗 | |
++ | インクリメント演算子(1加算する)。ポインタ、イテレータを1要素後ろを指すように移動。
int i=0, j=0; int v = ++i; //前置のインクリメント // iをインクリメントした後の値がvに格納される // ここでvは1、iは1 int w = j++; //後置のインクリメント //jの値をwに格納したあとjはインクリメントされる // ここでwは0、jは1 int *p = &i; int x = *p++; // int x = *(p++);と同じ //xにはpのインクリメントされる前の //アドレスを間接参照した値が格納される int y = (*p)++; // yにはpの参照先の値が格納され、 //後にその参照先の値がインクリメントされる //p自体は変化しない | |
- | 減算の二項演算子。負の符号を表す単項演算子。浮動小数点数リテラルの指数の符号。 | |
-- | ディクリメント演算子(1減算する)。ポインタ、イテレータを1要素手前を指すように移動。 | |
/ | 除算演算子。整数同士を除算した場合結果もまた整数で少数は切り捨てられることに注意。ゼロ除算に注意。boost.filesystemではpathの連結用演算子としてオーバーロードされている。C++20のchronoでは日付を表す 2020y/January/1 | |
//コメント | 一行コメント。 //から行末までコメントとして無視して解釈される | |
/*コメント*/ | 複数行対応コメント。古い時代のC言語ではプリプロセッサのトークン連結(現在の##)にも用いられた。 | |
% | 剰余演算子。boost.formatライブラリでは変数を連続して渡すためにオーバーロードされている。別言語のC++/CLIではGC管理されたオブジェクトに対するトラッキング参照(C++のT&に似ている)としても使用される。 | |
= | 代入演算子、コンストラクタ呼び出し、デフォルト引数、テンプレート仮引数のデフォルト型やデフォルト引数、コンセプトの定義(C++20)
std::string s = "hello"; // コンストラクタ呼び出し(コピー初期化) // stringコンストラクタでstringの一時オブジェクトが作られてから // (stringを引数に取る)ムーブ、コピーコンストラクタが呼ばれる。 // だが一時オブジェクトの作成は省略されうる。 s = "world!"; //代入演算子呼び出し int a, b; a = b = 0; //右から結合する。結果としてa、bともにゼロが代入される if (auto v = f()){} // f()の戻り値でvが構築されそのvをifが評価する void func(int arg = 3); //デフォルト引数 //テンプレートのデフォルト型、デフォルト引数 //下記例の後者はenable_ifを使いSFINAEをするために //デフォルト型を指定する場所を利用しているだけ。 template <class T = int, class = typename std::enable_if<is_xxx<T>{}>::type> void g() {} //autoを使用した場合は初期化値から型が推論される。 auto c = 0.0; //変数cはdouble型 //コンセプトの定義(C++20) template <class T> concept ConceptName = std::is_integral_v<T>; //コンセプトを用いてautoに制約を付加した使い方ができる。(この場合autoは省略可)(C++20) ConceptName auto d = 0.0; //変数dはdouble型だがコンセプトの制約を //満たしていない場合コンパイルエラーとなる | |
[ = ] | ラムダ式のコピーキャプチャ指定。およびC++14のラムダ式で新しい変数を宣言する際の初期化子として現れる。
[=, &y](){};//使用するローカル変数は全てコピーキャプチャ。 //ただしyは参照キャプチャ [x = std::move(v)](){}; //vをムーブしてxという名前で宣言 | |
= | 名前空間またはテンプレートまたは型の別名指定
namespace 新しい別名 = 名前空間; using 新しい別名 = 型名; | |
virtual メンバ関数宣言 = 0 | 純粋仮想関数の宣言 | |
メンバ関数宣言 = default; | コンストラクタや代入演算子などの特殊メンバ関数を可能であれば明示的に生成する。C++20から三分比較演算子<=>と ==演算子に =default;指定し他の比較演算子を生成可能。 | |
関数宣言 = delete; | 関数を明示的に削除されたものとして定義する。 | |
== | 等値比較。組み込みの比較演算子の戻り値型はbool型。比較演算子を用いて浮動小数点数を比較する際には注意が必要。
assert( 1+3 == 2+2 ); | |
!= | 非等値比較。C++20からは==が定義されていれば自動生成されるようになる。 | |
>= | 比較 大なりまたは等値 | |
<= | 比較 小なりまたは等値 | |
<=> | C++20より導入される三分比較演算子(通称 宇宙船演算子)。比較演算に厳密な意味を与え、他の比較演算子(<,>,<=,>=)の自動生成が可能になる。また定義がdefaultedな場合は==演算子が暗黙的に定義される。
struct T { // 全ての要素を直線的に並べられるられるものはstrong_orderingを返し、 // ==でtrueを返しても実際は異なるもので外部から区別が可能なものが // ある場合weak_orderingを返し、 //そもそも比較が不適当な要素を含む場合にはpartial_orderingを返すこと。 // strong_ordering の例 整数同士の比較 // weak_ordering の例 英大文字小文字を区別しないクラス // 'A'=='a'にtrueを返すが isupperなどで区別が可能 // partial_ordering の例 floatのNaNなど比較が不適当な場合 std::weak_ordering operator <=> (const T& rhs) const { if( toupper(val) < toupper(rhs.val) ) return std::weak_ordering::less; //... } char val{}; }; | |
<<= | 左シフトして代入 | |
>>= | 右シフトして代入 | |
+= | 加算して代入。std::basic_stringにおいては文字列を追加する。
int i=5; i += 3; //左辺と右辺を加算し、その結果を左辺に代入する assert(i == 8); std::string s = "Hello"; s += " World!"; assert(s == "Hello World!"); | |
-= | 減算して代入 | |
*= | 乗算して代入 | |
/= | 除算して代入。boost.filesystemのpath、property_treeのstring_pathでは連結代入用演算子としてオーバーロードされている | |
|= | ビットORして代入 | |
&= | ビットANDして代入 | |
%= | 剰余を代入 | |
^= | ビットXORして代入 | |
! | (エクスクラメーションマーク) 論理否定演算子。また型変換演算子 operator ポインタ型()等とともにオーバーロードされオブジェクトの状態をbool値として調べることができるようによく利用される。ただしこれはC++11以降ではexplicit operator bool()だけで事が足りるようになった。変わったオーバーロードがされていなければ「!!式」とすれば明示的に式をbool値へ変換できることになる。 C++23では if ! consteval として if consteval の否定として使える。 bool result = !true; assert(result == false); | |
!クラスと同じ名前() | クラス内でデストラクタと同じように宣言されている場合は別言語のC++/CLIにおいてファイナライザを表す。そうでなければ単にクラスのインスタンスを作成して論理否定演算子を呼び出しているだけだろう。 | |
^ | (ハット、サーカムフレックス) ビットXOR。 別言語のC++/CLIではGC管理されたハンドル(C++のT*に似ている)を表すことにも使用される。 unsigned value = x ^ 0b00000100; //xの下から3bit目をビット反転させる | |
& | ビットAND
unsigned value = x & 0xFF; //下位8bitを取り出す | |
式 && 式 | 論理積。左の式が偽なら右の式は評価されない。ただしオーバーロードされている場合は両方の式が評価されさらにその順序は不定。
if (x == 1 && y) puts("xは1と等しく尚且つyをbool値として評価するとtrueであった"); | |
&変数や関数 | アドレス演算子。変数や関数のアドレス取得。ただしオーバーロードされて別の意味になっている場合もありえるので確実を求めるならstd::addressof関数が利用できる。
int x=0; int* ptr = &x; | |
&&ラベル名 | gcc拡張でラベルのアドレスを取得する。 | |
型名& | 左辺値参照(単に参照といえば普通はこれ)。宣言する場合は初期化が必須(externを除く)。constな参照は一時オブジェクトを束縛してその寿命を参照と同じ期間まで延長できる。クラスのメンバに持たせるとデフォルトの代入演算子が使用できなくなる。常に参照先のオブジェクトの寿命に注意が必要。関数の戻り値型としてはオブジェクトの寿命について理解していない限り使用すべきではない。
//別名を付ける int i=0; int& j=i; i=2; assert( j == 2 ); //関数仮引数として使う一般的な使用例 void func1(const std::string& s) { cout << s << endl; } //一時オブジェクトの束縛。ただし必要となる場面はあまり無い。 int const& read_only_integer = int(); //OK //一時オブジェクトは直接でないと束縛できない auto const& r = *make_unique<int>(); // NG // すでに参照先は寿命切れで r を使うと未定義動作 std::string& func2() { // 未定義動作につながる std::string str("hello"); return str; // NG 非staticローカル変数strの寿命はここまで } const int& func3(const int& i) { return i; } const int& r = func3(1); // NG 直接でないと束縛できない // 整数リテラルは一時変数であり完全式の終わりですでに破棄済み void alloc_int(int*& r) { //int* への参照 r = new int(0); } | |
型名&& | 右辺値参照。しかしながら型名がauto&&の場合や関数テンプレートの仮引数においてそのテンプレートパラメータ型&&の場合に左辺値が渡されると型名&&は左辺値参照に推論される(Forwarding References)。つまりForwarding Referencesで受けた変数は無条件にstd::moveできない(代わりにstd::forwardを使う)。上記左辺値参照の項目の注意点も参照せよ。右辺値参照の場合constが付いていなくても一時変数を束縛できる。
//一時オブジェクトなど右辺値のstd::stringのみ受け取れる void func1(std::string&& t) { } //どんな型の右辺値、左辺値でも受け取れる template <class T> void func2(T&& t) { } | |
戻り値型 (&名前)(仮引数リスト) | 戻り値型 (仮引数リスト)のシグネチャを持つ関数への参照。名前は場合により省略可。 「名前」部分が名前(引数リスト)という形式の場合は「戻り値型 (仮引数リスト)の関数への参照」を返す関数宣言となる。 | |
型名 (&名前)[整数] | 型名[整数]という配列への参照。名前は場合により省略可。 「名前」部分が名前(引数リスト)という形式の場合は「型名[整数]という配列への参照」を返す関数宣言となる。 template <class T, size_t N> void f(T (&arr)[N]) { cout << N << endl; //テンプレートを用いることで配列長を得ることが可能 } int a[10]; f(a); | |
[ & ] | ラムダ式の参照キャプチャ指定
[&y]{}; //yを参照キャプチャ [&, v]{}; //使用するローカル変数を全て参照キャプチャ。 //ただしvはコピーキャプチャ。 | |
メンバ関数宣言 & | この関数はクラスのインスタンスが左辺値のときのみ呼べる。
struct s { void f(int) & {} }; s v; v.f(0); //OK vは左辺値 s().f(0); //ill-formed s()は右辺値 | |
メンバ関数宣言 && | この関数はクラスのインスタンスが右辺値のときのみ呼べる。rvalue reference for *this | |
| | (バーティカルライン)ビットOR。boost.rangeライブラリではアダプタを適用するパイプ演算子としてオーバーロードされている。
assert((0b1100 | 0b0011) == 0b1111); | |
式 || 式 | 論理和。左の式が真なら右の式は評価されない。ただしオーバーロードされている場合は両方の式が評価されさらにその順序は不定。 | |
requires 式 && もしくは || 式 | requires節(C++20)において制約を複数個指定する。通常の論理積、論理和と使い方は似ている。通常の論理積、論理和を使う場合は()で括ること。
// UがコンセプトC1を満たすかもしくは整数であれば制約を満たす関数を定義 template <class U> requires C1<U> || std::is_integral_v<U> void func(U) {} | |
, | カンマ演算子。前から順に評価される。しかしながらオーバーロードされている場合に評価順序は不定。また下記項目の関数引数の区切りの評価順序は不定で混同に注意が必要。全体を()で括らないと基本的に変数や関数の複数宣言と解釈されてしまうため括るべき。
auto v = (f(), g(), h()); //f(),g(),h()の順に呼び出され最後のh()の戻り値がvに代入される // 応用例としてmutexのlock、unlockがワンライナーで記述できる // まずlock_guardの一時変数が作られコンストラクタでmtx.lock()が // 呼ばれ次に flag = trueが評価され、そのあと完全式の終わりに // lock_guardのデストラクタが呼ばれそこでmtx.unlock()が呼ばれる (lock_guard<mutex>{mtx}, flag = true); ((lock_guard<mutex>)mtx, flag = true); template <class T> auto k(T t) -> decltype(t.size(), t.front(), std::declval<void>()); //SFINAEをする目的でdecltypeの中で用いてt.size()と //t.front()が有効な時だけ関数kが使えるようになる。 //decltype中の式は実際には評価されない。 //関数kの戻り値は最後のdeclval<void>()からvoidとなる。 | |
, | 関数引数リストの区切り。引数の評価順序は不定でsequenced beforeの関係もこれだけでは入らないことに注意。
func(f(), std::unique_ptr<int>(new int)); //bad // f(), unique_ptr(), new intの評価順序は不定 // ただし new int は unique_ptr() よりは前に呼ばれる // 仮に new int、f()、unique_ptr()の順で呼び出されるとすると、 // f()が途中で例外を投げた場合は new intで確保された領域が // リークすることになる // そこでnewを直接使用せずmake_uniqueを使用する func(f(), std::make_unique<int>()); // OK // 若しくは一旦スマートポインタに名前を付けるとよい。 std::unique_ptr<int> p(new int); //すぐにunique_ptrを構築 func(f(), p); //OK | |
, | 単にリストの区切りとして用いられる。初期化リスト内の要素の区切り(前から順に評価される(g++4.9.1未満は不定))。継承元クラスの複数指定(多重継承)、列挙型(enum)の列挙子を定義する際の区切り、(テンプレート)仮引数リストの区切り、関数風マクロ引数リストの区切り、ラムダ式のキャプチャリストの区切り、属性の複数指定、構造体束縛の変数名の区切り。 | |
型名 名前, 名前; | 変数や関数の複数宣言。個別に型を記述した場合と同じ。int* x, y;と記述した場合xはint*型、yはint型になる。yもint*型にするには int* x, *y;と記述する。参照の&も初期化が必須なこと以外同様。
int v=0,w,*x,y{}, *(*z)(), a(); // int v=0; int w; int* x; int y{}; int* (*z)(); int a(); に同じ // int a(); は関数宣言であることに注意 | |
~ | (チルダ)ビット否定。gcc拡張で__complex__もしくは_Complex型の複素共役を求める。全ビットを1にするために = ~0u を使用するのは汎用性がないため = -1 の方が良い。 | |
~クラスと同じ名前() | クラスのメンバ関数として宣言されているならデストラクタ宣言。メソッドとして呼び出されているならデストラクタの明示的な呼び出し(配置newとセットで使う)。それ以外なら単にクラスのインスタンスを作成してビット否定演算子を呼び出しているだけだろう。 | |
< | 比較 小なり
int x = 1; assert(x < 2); | |
> | 比較 大なり | |
<< | 左シフト演算子。ストリームクラスではオーバーロードされ、ストリーム出力に使用される。
unsigned x = 1u << 8; //1を8bit左シフトする。x=256 std::cout << "result:" << x; //標準出力に「result:256」と出力 | |
>> | 右シフト演算子。ストリームクラスではオーバーロードされ、ストリーム入力に使用される。 | |
<テンプレート引数リスト> | テンプレート型の定義、テンプレート引数の指定、テンプレートの特殊化。またC++14以降の変数テンプレート。C++20のコンセプト。C++20ではラムダ式にも現れる。コンセプト名をclassやtypenameの代わりに記述することで制約を付加できる(C++20)
template <class T = void> struct S { }; template <> struct S<int> { }; //Sをint型に特殊化 // 最初の<>はSのテンプレート引数を全て特殊化したため空になっただけ template struct S<std::string>; //Sをstd::string型で明示的にインスタンス化 std::vector<double> v; S<> a; //テンプレート引数を省略した形 template <class T> T Val{}; //変数テンプレート Val<int>; //これは型ではなく値 template <auto v> //非型テンプレート (C++17) struct s{}; s<3> o; //非型テンプレートに制約を付加する場合(C++20)は template <ConceptName auto v>となる | |
static_cast<型名>(値) | キャスト。static_cast、const_cast、dynamic_cast、reinterpret_castの4種。これらのキャストを利用しても元々未定義動作をするコードが安全になるわけではないことに注意。
const int a = 1; *const_cast<int*>(&a) = 2; // 未定義動作 | |
#include <ファイル名> | include命令。指定されたファイルを読み込んでこの位置に貼り付ける。<>の代わりに""で大抵の場合代用可能だが<>は主に処理系の提供するヘッダや他のライブラリを読み込むのに使用される。C++17より__has_include()内に<>と""も現れる。 | |
関数名<<<実行コンフィグ>>>(引数リスト) | CUDA拡張でカーネル関数を呼び出す。 | |
(式) | 式の結合順序を指定。2*(3+4)など。結合順序が変わらなくても順序を明示してコードを読みやすくしたり、単に見た目を改善するために使用されることもしばしば。関数風マクロの仮引数は意図しない解釈のされ方を少しでも防ぐため必ずと言っていいほど()で囲まれる。#define MACROFUNC(a) ((a)->member) 文法の曖昧さを解決するためにも用いられる。template <bool A = (1 > 0)> 関数名を囲い意図しない関数マクロの展開を防ぐことにも用いられる。maxというマクロが定義されている環境で競合を回避してテンプレート関数のstd::maxを使用するには(std::max)(1,2);のようにする。ADLの回避にも使用可。関数風マクロに渡す引数に「,」が含まれていると関数風マクロの区切りと解釈されてしまうのでその回避にも使用可能(ただし()がそのままトークンに残る)。MACROF((arg1<int,char>{}), arg2); 通常の関数の実引数として使用した場合は()内の,はカンマ演算子となる。 int x=0; decltype(auto) y = x; // int 型 decltype(auto) z = (x); // int& 型 int& r = x; decltype(auto) s = r; // int& 型 decltype(auto) func() { int a = 1; return (a); //NG int&型となりdangling referenceとなる } | |
キーワード等 (条件など) | キーワード部分には if、if constexpr、for、while、switch、sizeof... 、alignof、alignas、typeid、decltype、catch、throw、noexcept、new、new auto、static_assert、asm、explicitなどが当てはまりカッコ内にその条件、型、変数などを記述する。gcc拡張で属性を使用するには __attribute__ ((属性)) のように二重に括弧が必要。
if (x != nullptr) { new (x) int{}; //配置new (注意が必要な機能) auto ip = new (std::nothrow) int{}; //失敗すると例外を投げずに //ヌルポインタ値を返す auto dp = new auto (0.0); //初期化値から型を推論してnew void* vp = operator new (8); //指定したサイズの領域を確保するだけ } // new (Arg1, Arg2) T という文法は内部で // operator new (sizeof(T), Arg1, Arg2)を呼び出す | |
関数名(実引数リスト) | 関数呼び出し、関数呼び出し演算子の呼び出し。関数風マクロの展開も同じ形。「関数名」は関数ポインタまたは関数への参照または関数オブジェクトでもよい。
{ f(); //fが関数名、関数ポインタ、関数への参照の場合は 関数呼び出し g(); //gが関数オブジェクトの場合は 関数呼び出し演算子の呼び出し h(); //hが型名の場合はこれは関数呼び出しではない(オブジェクトの構築) k(); //C89以前のC言語の場合 関数呼び出しだがkが宣言されて // いない場合に暗黙的に int k();が宣言されることに注意。 // 関数の外にあるならこれは関数呼び出しではなく int k();の宣言 std::vector<int> v; v.push_back(0); //vectorクラスのpush_backメンバ関数の呼び出し auto neg = std::negate<int>()(1); // 前者の()はオブジェクトの構築 //後者の()は構築された関数オブジェクトの関数呼び出し演算子の呼び出し } | |
戻り値型 関数名(仮引数リスト) | 関数宣言。
int sum(int a, int b); int sum(int,int); //単なる宣言や変数を使用しない場合は //仮引数は型だけでもよい auto sum(int a, int b); // C++14以降なら場合により可(->の項も参照) //(C++20)コンセプトで引数に制約を掛けたテンプレート関数の簡略表記 void f(SomeConcept auto arg){} | |
戻り値型 (仮引数リスト) | 戻り値型 (仮引数リスト)というシグネチャを持つ関数型。std::result_ofに渡す場合は違った意味として解釈され、「戻り値型」部分は呼び出し可能な型として扱われる。result_ofのように関数型を本来の意味から外れて単なる型リストとして扱うこともしばしばある。
//戻り値が int で引数が void の関数などを格納できる std::function<int()> funobj; struct st{ char operator ()(double d); }; std::result_of<st(double)>::type val1; //char型 int f(void*) { return 0; } //普通の関数をresult_ofに渡すには参照型にする必要がある std::result_of<decltype(f)& (void*)>::type val2; //int型 | |
(this 型名 仮引数) | C++23のdeducing this。メンバ関数もしくはラムダ式の仮引数として呼び出し元のインスタンスを明示的に取得できる。 これによってconst修飾子、ref修飾子の有無などの違いを統一して一つの関数として記述することが可能となる。また再帰ラムダの記述を簡素にできたりするその他の恩恵もある。 struct S { template <class T> void f(this T&& self, string str) { if(is_const_v<remove_reference_t<T>>) {} } }; S{}.f("Hello"); // 仮引数selfにはこのS{}が渡される。 // 実引数の"Hello"は2番の仮引数strに渡る。 | |
new 型名(実引数リスト) または {実引数リスト} | new演算子。動的にオブジェクトを構築してそのポインタを返す。初期化の注意点については下記項目を参照。C++14以降からstd::make_uniquep=new std::string; //デフォルト初期化されコンストラクタが呼ばれる q=new int; //デフォルト初期化され組み込み型なので値は不定値 r=new int(); //値初期化される | |
型名 変数名 (実引数リスト) または {実引数リスト} または = {実引数リスト} | コンストラクタを呼び出してインスタンスを作成する。上記関数宣言の形式と区別がつかない場合は関数宣言と見なされる。()の代わりに{}や={}を使用してリスト初期化する場合は空の場合を除いてstd::initializer_list<>を引数に取るコンストラクタが優先されるので注意。下記の初期化リストの項目も参照。C++20から集成体初期化が()でも行えるようになった。
std::vector<int> a(5); //vector(size_type)を呼び出し //aは値が0の要素を5個含むvector std::vector<int> b{5}; //vector(initializer_list<int>)を呼び出し //bは値が5の要素を1個含むvector int c1; //c1はデフォルト初期化され組み込み型なので不定値となる int c2{}; //c2は値初期化されて0となる int c3(0); //c3は0で初期化される std::vector<int> d; //デフォルトコンストラクタ呼び出し std::vector<int> e{}; //デフォルトコンストラクタ呼び出し std::vector<int> f();//std::vector<int>が戻り値型で //引数リストが空の関数宣言と見なされる int g((int())); // int g; を宣言し値0の一時オブジェクトで初期化 int g(int()); // int g(int (*)()); という関数宣言と見なされる int ar[](1,2); //集成体初期化(C++20) | |
型名(実引数リスト) または 型名{実引数リスト} | 関数形式の明示的な型変換。(必要であれば型の変換を行ったり)コンストラクタを呼び出すなどして一時オブジェクトを作成。()の代わりに{}を使用する場合は上記の注意を参照。C++23からauto(値)が使えるようになる(decay-copy)。
auto s = std::string("abc") + "defg"; auto v = int() * 1; // 組み込み型のintは値初期化され0となる | |
型名(宣言子) | 宣言子が()で囲まれている宣言。上記の関数形式の明示的な型変換と区別がつかない場合はこちらの宣言として解釈される。
T(a); T a; //上はこれと同じ //doubleを引数にとりintを返す関数ポインタ型のnameという名前の変数 int (*name)(double); //doubleを引数にとりint*を返すname関数の宣言 int *name(double); | |
クラスと同じ名前(仮引数リスト) | コンストラクタの宣言。上記「:」のコンストラクタのメンバ初期化リストの項目も参照。
class S { public: S(); //デフォルトコンストラクタ explicit S(int i); //1引数のコンストラクタはexplicitを付けることを検討せよ S(const S& rhs); //コピーコンストラクタ S(S&& rhs); //ムーブコンストラクタ ~S(); //デストラクタ S& operator = (const S& rhs); //コピー代入演算子 S& operator = (S&& rhs); //ムーブ代入演算子 }; | |
(型名)変数 | 型のキャスト(コンストラクタの呼び出し、型変換演算子の呼び出し)。キャストにはstatic_cast<>等の新形式のキャストを使用すべき。
(void)func(); // void型へのキャストで戻り値を使用しないことを明示。 // unused variableの警告消しにも (C++17より // [[maybe_unused]]属性が利用可) | |
関数宣言 throw(型リスト) | 古い形式の動的例外指定。この関数が投げうる例外を指定する。主にthrow()として例外を投げない表明として用いられていたが現在ではnoexceptを使用したほうが良い。
void f1() throw(); //古い形式の例外を投げない表明 void f2() noexcept; //例外を投げない表明 void f3() noexcept(true); //trueなら投げない、falseなら投げうる表明 | |
structかclassまたはunion 中略{ いろいろ }中略; | クラスまたは共用体の定義部分。最後の;は必須。最後の中略部分は必要に応じてこの型(もしくはそのポインタ型など)の変数を定義できる。またはtypedef structの形なら別の型名を付けることができる。C言語においてはtypedefを用いると型を宣言するたびにstructキーワードを使う必要がないので利便性が向上する。
struct s { int v; } *ptr, obj, arr[] = {0, 1, 2}; //上は下と同じ struct s { int v; }; s* ptr; s obj; s arr[] = {0, 1, 2}; | |
enum 中略{ 列挙子, 列挙子=定数式, } | 列挙型の定義部分。=で値を割り当てられる。割り当てないと最初の列挙子の場合は値が0になり、それ以外の列挙子は前の列挙子の値に1加算した値となる。 | |
{ 値, 値, 値 } | 初期化リスト。集成体の初期化、コンストラクタ呼び出し。std::initializer_list<要素の型>型にもなる(要素の寿命に注意)。配列やコンストラクタの無いクラスのメンバを初期化するときに省略された要素は値初期化される。staticメンバや匿名ビットフィールドは飛ばして無視される。またリスト内の式は前から順に評価される(g++4.9.1未満は不定)。narrowing conversionはできない。
struct s { int x,y,z; }; //この{};は構造体の定義 s a; //x,y,zは不定値 s a{}; //x,y,zは0で初期化される s a = {}; //同上 s a = {0}; //結果として同上 s a = {1}; //x=1,y=0,z=0 s a{1}; //同上 struct t { //この{};は構造体の定義 int x,y,z=1; std::string str; t():x(0){} //この{}はコンストラクタ本体 }; //以下のいずれの場合もコンストラクタが呼ばれる t a; // x=0, yは不定値, z=1, strは適切に初期化される // xはメンバ初期化リストで初期化されているため // zはデフォルトメンバ初期化子で初期化されているため // strはstd::string型自体が適切なコンストラクタを持っているため t a{}; //同上 t a={}; //同上 struct u { //この{};は構造体の定義 int x,y,z; u(std::initializer_list<int> il) { //この{}はコンストラクタ本体 for(auto v : il) cout << v; } u(int a, int b, int c) {} //この{}はコンストラクタ本体 }; u a{ 0, 1, 2 }; // std::initializer_list<int>を // 引数に取るコンストラクタが呼ばれる u a={0,1,2}; //同上 u a(0,1,2); //intの引数を3つ取る方のコンストラクタが呼ばれる //上記のいずれもx,y,zを初期化している箇所がないために // いずれの場合もx,y,zはすべて不定値 auto x = { 0 }; //xはinitializer_list<int>型 auto y{ 0 }; //yはC++17より挙動が変更されint型になる //initializer_list<int>を構築。即席の配列として利用 for (auto v : { 2,4,6,8 } ) cout << v; void func(int); func({}); //関数引数の型(ここではint)を明示せずに構築 pair<int,int> f() { return {0, 1}; //戻り値がコピーリスト初期化される } | |
{ いろいろ } | ブロックスコープ。関数本体やラムダ式本体の定義部分。for、do、while、if、else、try、catchのブロック。スコープの範囲を抜ける時にローカル変数のデストラクタが呼ばれる。たとえばローカル変数のfstreamやlock_guardを宣言し使用している個所を{ }で囲うことでリソースを扱う部分を局所化し、早期にファイルやロックを解放できたりする。 またswitch文ではなるべく{}でスコープを導入しローカル変数を宣言する場合はさらに内側に{}でスコープを作りcase、defaultラベルを跨がないようにするべき。void f() { std::string str; { std::ifstream file("path"); file >> str; } //ここでfileのデストラクタが呼ばれファイルが解放される std::cout << str; } //ここでstrのデストラクタが呼ばれる | |
namespaceやextern 中略{ いろいろ } | namespaceスコープの指定。もしくはexternで言語リンケージを適用する範囲を指定する。namespace { 略 } で無名名前空間を表す。 | |
({ いろいろ }) | gcc拡張で複数の文を一つの式として扱える。
int x = ({ int y=0; y+1; }); //xには最後のy+1;の値が代入される | |
# | プリプロセッサ命令(関数風マクロ定義など)。
//関数風マクロを定義 // FUNC(0) がf(0)に置き換わる。 #define FUNC(arg) f(arg) # //単独の#に意味はない | |
# | 関数風マクロ内でマクロパラメータを""で括り文字列リテラル化する。
//引数paramを文字列リテラル化するTXTという名前の //関数風マクロを定義 TXT(hello)が"hello"に置き換わる。 #define TXT(param) (#param) | |
## | 関数風マクロ内でのトークン連結。またgcc拡張では ## __VA_ARGS__ とすることでこの可変長引数マクロの引数がゼロ個の場合に手前にある「,」を削除できる。 | |
#@ | VC拡張でマクロパラメータを''で囲い文字リテラル化する。 | |
小数点を含まない数値 | intもしくはそれより大きい型の整数リテラル。0以外の数字から始まる場合は10進数だが0から始まる場合は基数が異なる。下の項目を参照。 | |
小数点を含まない数値U | unsignedの整数リテラル。小文字のuも可。下記のLやLL、Zと組み合わせることができる。 | |
小数点を含まない数値L | long intもしくはそれより大きい型の整数リテラル。小文字のlも可。 | |
小数点を含まない数値LL | long long intの整数リテラル。小文字のllも可。 | |
小数点を含まない数値Z | (C++23) ptrdiff_t型を表す。Uと組合わせたZUもしくはUZの場合はsize_t型。小文字のz、zu、uzも可。 | |
小数点を含む数値L | long double型浮動小数点数リテラル。小文字のlも可。 | |
小数点を含む数値 | double型浮動小数点数リテラル | |
小数点を含む数値F | float型浮動小数点数リテラル。小文字のfも可。 | |
小数点を含む数値F16等 | (C++23) float16_t型浮動小数点数リテラル。その他F32,F64,F128もある。小文字のf16,f32,f64,f128も可。 | |
小数点を含む数値BF16 | (C++23) bfloat16_t型浮動小数点数リテラル。小文字のbf16も可。 | |
数値E指数 | 浮動小数点数の指数表記(基数は10)。小文字のeも可。 | |
数値il | 虚数のユーザー定義リテラル。std::complex<long double>型。(C++14) | |
数値if | 虚数のユーザー定義リテラル。std::complex<float>型。(C++14) | |
数値i | 虚数のユーザー定義リテラル。std::complex<double>型。(C++14) | |
小数点を含む数値iもしくはj | gcc拡張で虚数を表す。1.2fjならfloat _Complex型で虚部の値が1.2となる。 | |
I | C99の虚数単位。const float _Imaginary型。 | |
数値df、dd、dl | gcc拡張の10進浮動小数点数。それぞれ_Decima32、_Decimal64、_Decimal128型。大文字も可 | |
数値r、k、hr、ullk等 | gcc拡張の固定小数点数。大文字も可 | |
数値q、w | gcc拡張の浮動小数点数。大文字も可 | |
数値h、min、s、ms、us、ns | 時、分、秒、ミリ秒、マイクロ秒、ナノ秒のユーザー定義リテラル。std::chrono::duration | |
数値y、d | C++20のchronoで西暦年と日を表すユーザー定義リテラル。 | |
0x0〜9またはa〜fからなる数値 | 16進数リテラル。大文字の0X、A〜Fも可。
int val = 0x7F; // val == 127 | |
0x数値p指数 | C++17、C99もしくはgcc拡張で16進数で浮動小数点数リテラルを記述できる。但し指数部分は10進数で底は2。大文字の0XやPも可。
0x1.EP-3f; // (1 + 14/16) * (2の-3乗)のfloat型 | |
0b数値 | 2進数リテラル。大文字の0B数値も可。 (C++14) | |
0数値 | 8進数リテラル。
assert(015 == 13); | |
0 | 単に0と書いた場合は文法上8進数の零として解釈されていることになる。0はヌルポインタ定数として用いることもできるが、nullptrを使用するほうがよい。特殊な文法としては純粋仮想関数の宣言にも使われる(=0の項目参照)。クラスメンバの宣言部分における 型:0 はビットフィールドのゼロ幅指定で特別な意味を持つ(:の項目参照)。整数の0をbool型に変換した場合はfalse、0以外の値はtrueとなる。 | |
数値途中の' | 数値途中のシングルクォーテーションマークは数値の区切り。無視して解釈される。 (C++14)
| |
'文字' | 文字リテラル。接頭辞が無く単独の文字ならchar型(C言語の場合はint型)、複数の文字ならint型のマルチ文字リテラル。Lの接頭辞はwchar_t型、uの接頭辞はchar16_t型、Uの接頭辞はchar32_t型。 C++17ではu8の接頭辞でエンコーディングにUTF-8を指定できる。 | |
"文字列" | 文字列リテラル。const char型の配列。文字列リテラルは最後に'\0'が付加される。他のリテラルとは異なり文字列リテラルそのものへのポインタはスコープを超えて持ち回せる。文字列リテラルや文字列へのポインタ同士を==や!=を用いて比較しても文字列の比較とはならない。 | |
"文字列" "文字列" | 連続した文字列リテラルは連結され一つの文字列リテラルと解釈される。行を跨いで連結することも可能。 | |
extern "C" または "C++" | 言語リンケージを指定。外部リンケージを持った関数型や関数名、変数に影響する。 | |
#include "ファイル名" | include命令。指定されたファイルを読み込んでこの位置に貼り付ける。主にユーザーの用意したファイルを読み込むのに使用される。読み込みに失敗した場合は #include <ファイル名>にフォールバックされる。 | |
L"文字列" | ワイド文字列リテラル。const wchar_t型の配列。 | |
u8"文字列" | エンコーディングがUTF-8の文字列リテラル。const char型の配列。 | |
u"文字列" | char16_t文字列リテラル。const char16_t型の配列。 | |
U"文字列" | char32_t文字列リテラル。const char32_t型の配列。 | |
R"区切り用文字列(文字列)区切り用文字列" | Raw文字列リテラル。区切り用文字列は自由に決めて囲うことができる、省略可。エスケープが不要で改行も見た目のまま表現できる。R接頭辞は上記L,u8,u,U接頭辞と組み合わせることができる。
auto str = LR"(hello world)"; assert(str == L"hello\nworld"s); | |
"文字列"s | basic_stringリテラル。"文字列"sならstd::string型、L"文字列"sならstd::wstring型など。(C++14) | |
"文字列"sv | basic_string_viewリテラル。(C++17) | |
"%02d %f %s"など | printf、scanf系またはstrftimeなどの関数に渡す書式指定文字列。単なる文字列だがこういった関数の中でこれらの記号は特別な意味として解釈される。printfの文法。使用される記号は%.+- 0*#[^]{:}<>=など。scanfではfloatとdoubleの区別をつける必要があるなどその差異に注意が必要。boost.formatでは"%1% %2$d"なども使用される。マクロのPRI〜、SCN〜は inttypes.h ヘッダでdefineされており stdint.hで定義されている型(int8_tなど)をprintf、scanfなどに渡すときに使用する書式。std.formatはPythonに基づく文法(仮)を採用予定。 | |
"^[0-9]+(a|b)?"など | regex系のオブジェクトに渡す正規表現。単なる文字列だが正規表現ライブラリでこれらの記号は特別な意味として解釈される。使用される記号は^$[-](|).*+?:{,}\など。std.regexはデフォルトでECMAScriptに基づく文法を採用し、boost.regexはデフォルトでPerlに基づく文法を採用している。 | |
\文字 | (円記号、英文フォントではバックスラッシュ)文字(列)リテラル内において続く1文字をエスケープする。\'、\"、\?、\\、\a、\b、\f、\n、\r、\t、\vのうちのどれか。例えば\tは水平タブ文字、\\は\に変換される。改行としてUnixでは\n、Windowsでは\r\nがよく用いられる。gcc拡張では\eはASCIIのESCに変換される。
//たとえば c:\folder\document.txt ファイルを開くときは以下のように std::ifstream f("c:\\folder\\document.txt"); // \を\\にする事が必要 //もしそのまま書いた場合は'\f'がform feed制御文字になってしまう。 //'\d'は解釈できずコンパイルエラーとなるか独自のコンパイラ拡張に //より何らかの文字へ変換されてそのままコンパイルが通るかもしれない //ファイルパスはエスケープの必要がない/(スラッシュ)を //使うのがわかりやすい (C++というよりはOSのTips) std::ifstream f("c:/folder/document.txt"); //Raw文字列リテラルを使う方法もある。この場合Rと()が必要。 std::ifstream f(R"(c:\folder\document.txt)"); | |
\八進数 | 文字を8進数の文字コードで指定。最大三桁。例えば\0はNUL文字に相当。 | |
\x十六進数 | 文字を16進数の文字コードで指定 | |
\u十六進数 | UCS-4文字を表す。コードポイントの上位16bitは0000で固定。下位16bitを16進数で指定 | |
\U十六進数 | UCS-4文字を16進数の文字コードで指定 | |
\o{八進数} | (C++23) 文字を8進数の文字コードで指定。\八進数の場合とは異なり桁数に制限がない。 | |
\x{十六進数} | (C++23) 文字を16進数の文字コードで指定。\xよりも範囲がわかりやすい。 | |
\u{十六進数} | (C++23) UCS-4文字を表す。\uよりも範囲がわかりやすい。 | |
\N{ユニバーサル文字名} | (C++23) 文字を名前で指定する。\N{HIRAGANA LETTER A}は文字「あ」を意味する。 | |
\改行。つまり行末の\ | 直後の改行を取り除きその行と次の行を連結する。マクロ定義で改行する場合には必須となる。 | |
_ | アンダースコアはアルファベットなどと同じく識別子名に使用できる。またメンバ変数を「name_」などと名付けるコーディング規約など様々なスタイルが存在する。ただし「__」(アンダースコア2つ)が含まれるかまたは「_大文字」で始まる識別子はすべての場所で予約されている。「_」で始まる識別子はグローバル名前空間内で予約されている。使用しない変数や、型名だけで機能が自明なstd::lock_guard変数名などを単に「_」とする例もあるが衝突しやすい名前である。ローカライゼーション用にgettextライブラリと組み合わせて「_("msg")」,「N_("")」などが使用されることがある。 | |
_t | 標準ライブラリで名前の最後に「_t」を付けたものは型名を表している(std::size_tなど)、またC++14以降の<type_traits>ヘッダのメタ関数名の末尾の「_t」はusingを使ったtype aliasで結果の型を表す(std::add_const_t<T> は typename std::add_const<T>::type と同じ)。 | |
_v | C++17の標準ライブラリでは上記「_t」と同じように「_v」を最後に付けて ::valueを省略可能。 | |
_T | WindowsSDKにおいて_Tはマルチバイト文字とワイド文字の切り替えマクロ。 | |
_文字 | プレースホルダ。アンダースコアと一文字の識別子またはアンダースコア単独の識別子はstd.bind、boost.bind、boost.lambda、boost.phoenix、boost.mpl、boost.typeerasure、boost.spiritなどのライブラリで placeholder として用いられている。_1や_aや_など。boost.xpressiveではマッチする文字種の指定などにも。 | |
リテラル_接尾辞 | ユーザー定義リテラル。接尾辞は一般に_から始まる。アンダースコア以外の文字から始まる接尾辞は予約されている。
auto speed = 10_mile / 30min; auto graph = "{ a -> b -> c; a ->d; }"_digraph_dot; | |
operator "" 接尾辞(引数) | ユーザー定義リテラルの定義
constexpr LengthSI operator "" _mile(unsigned long long int val) { return LengthSI(val * 1609.344); } | |
operator 型名() | 型変換演算子。explicitを付けることを検討せよ。
struct s { explicit operator bool() const { return true; } }; s object; if (object) {} | |
operator 演算子(引数リスト) | 演算子の定義。演算子の呼び出し。
struct s { bool operator == (s const& rhs) const { //演算子の定義 return this->val == rhs.val; } int val = 0; }; s x,y; x.operator == (y);// ==演算子の呼び出し x == y; //同じく | |
operator ()(引数リスト) | 関数呼び出し演算子。これを定義したクラスは関数オブジェクトと呼ばれる。 | |
operator ++() | 前置インクリメント。--の場合は前置ディクリメント。 | |
operator ++(int) | 後置インクリメント。--の場合は後置ディクリメント。intの仮引数は前置と後置を区別するためのダミー引数。 | |
スペース、タブ文字、改行等(ホワイトスペース) | トークンの区切り。基本的にこれが無いと区切りが分からない場合以外はいくつあろうが関係ない。例外としては文字(列)リテラル内や、関数風マクロとオブジェクト風マクロの区別やマクロでの改行など。またキーワードや識別子など連続している必要のある単語内に挟むことは基本的にはできない。 | |
アルファベットがすべて大文字の名前 | 慣用的にマクロであることを示すことが多い。
#define PREVENT_REPLACE int max PREVENT_REPLACE (void); //お行儀の悪い小文字のmaxという関数風マクロが定義されて //いる環境で同名の通常関数をマクロに干渉されないように宣言している。 //これはマクロが前から順に置き換えられるが関数風マクロは //「 トークン(略) 」 の形でしか置き換えられないため。 | |
and、and_eq、bitor、or_eq、or、xor_eq、xor、not、compl、not_eq、bitand | いずれも&&、&=、|、|=、||、^=、^、!、~、!=、&の代替表現
if (not x) { // if (!x) { に同じ } | |
<%、%>、<:、:>、%: | 何れも{、}、[、]、#の代替表現。
%:include <iostream> int main() <% return 0; %> | |
??文字 | ??に続く1文字はトライグラフ。例えば ??=は#と解釈される。C++17で廃止される。 | |
$ | 基本文字集合には含まれない。つまり普通は文字(列)リテラル以外では使用されない文字(識別子として使用される例は無いわけではない) | |
@ | 基本文字集合には含まれない。VC拡張で#@の項目参照。Objective-Cに現れる。また規格文章や説明などで@=などとして+=や-=などの演算子をまとめて表記することに用いられる。 | |
` | 基本文字集合には含まれない。 | |
<?、>?、<?=、>?= | 古いgcc拡張で最小値または最大値を求める。=の付いているものは+=などと同じで求めた値を左辺に代入する。 | |
[*] | C++ではなくC99の機能で関数プロトタイプの配列引数が可変長であることを表明する。
void h(double multidim[*][*]); void f(size_t, int[const *]); //C99だと[]の中に修飾子が書ける void f(size_t n, int ar[const n]) { } //中身は結局のところ以下と同じ void h(double*); void f(size_t, int* const); void f(size_t n, int* const ar) {} //gを呼び出すときは10要素以上の配列を確実に渡す必要がある void g(int a[static 10]); //中身は結局のところ以下と同じ void g(int* a); | |
(型){ } | C++ではなくC99の機能で複合リテラル(compound literal)を表す。無名のオブジェクトを生成するがその値はlvalueである。上記designated initializerと組み合わせることもできる。
//C99の compound literal int* p = (int []){0,1,2}; //同じスコープならアドレスを後で利用可 | |
戻り値型 関数名(仮引数リスト) return 名前; { } | 古いgcc拡張で関数の戻り値に名前を付ける。
int f() return r; { r = 0; } | |
戻り値型 関数名(名前だけの仮引数リスト) 型名 名前; { } | C++ではなくK&R時代のC言語で引数の型名を後に書く形式。型安全ではない。
void f(a) int a; { // int a;を省略することもできる } void g(); //これもC言語においては型安全ではない // void g(void); のほうが良い | |
関数名(仮引数リスト) | C++ではなくC89以前のC言語で関数宣言の戻り値型を省略したもの。暗黙的に戻り値型はintとなる。
f(char* p); | |
T U N R A1 | テンプレートパラメータの名前としてよく利用される。Nは長さ、Rは戻り値型、Aは引数型などに | |
(ベクトル型)(要素,要素) | OpenCL C言語のベクトルリテラル。
float4 a = (float4)(1,2,3,4); float4 b = a.xyzw; //x y z wが個別の要素に対応 float2 c = a.s12; //sと16進数で要素を位置で指定する float2 d = a.odd; //奇数位置の要素。その他 even,hi,lowなど |
各種ライブラリでは演算子をオーバーロードして特殊な意味を持たせている場合があります。
boost.assignでは+=やカンマ演算子の,や関数呼び出し演算子の()をオーバーロードして使用。
boost.signals2では+=をスロットの接続に。
boost.serializationでは&や<<や>>を入出力の演算子として使用。 boost.lambdaやboost.xpressiveやboost.spiritやboost.protoなどは大量の演算子をオーバーロードして使用。boost.asioのyield_contextでは[]をエラーコードを格納するために使用。
説明の中で不定値としてあってもstaticもしくはグローバル変数の場合には最低限ゼロ初期化はされています。
C++17より組み込みの演算子の評価順序が定まっていればオーバーロードされた場合でも評価順序が同一となります。
標準のユーザー定義リテラルを使用するには事前に必要なヘッダのインクルードと using namespace std::literals; などとする必要があります。 [NS略 : 略]とか@とか^とかがよく出てくるのはObjective-C&C++
ビット演算子 ^ & | は比較演算子よりも優先順位が低いことに注意してください。
演算子の優先順位(cppreference) https://ja.cppreference.com/w/cpp/language/operator_precedence