名前空間
変種
操作

その他の演算子

提供: cppreference.com
< cpp‎ | language
 
 
C++言語
一般的なトピック
フロー制御
条件付き実行文
繰り返し文 (ループ)
ジャンプ文
関数
関数宣言
ラムダ関数宣言
inline 指定子
例外指定 (C++20未満)
noexcept 指定子 (C++11)
例外
名前空間
指定子
decltype (C++11)
auto (C++11)
alignas (C++11)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点
文字 - 文字列 - nullptr (C++11)
ユーザ定義 (C++11)
ユーティリティ
属性 (C++11)
typedef 宣言
型エイリアス宣言 (C++11)
キャスト
暗黙の変換 - 明示的な変換
static_cast - dynamic_cast
const_cast - reinterpret_cast
メモリ確保
クラス
クラス固有の関数特性
特別なメンバ関数
テンプレート
その他
 
一般
値カテゴリ (lvalue, rvalue, xvalue)
評価順序 (副作用完了点)
定数式
未評価式
一次式
ラムダ式(C++11)
リテラル
整数リテラル
浮動小数点リテラル
ブーリアンリテラル
文字リテラル および エスケープシーケンス
文字列リテラル
ヌルポインタリテラル(C++11)
ユーザ定義リテラル(C++11)
演算子
代入演算子: a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b
インクリメントとデクリメント: ++a, --a, a++, a--
算術演算子: +a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b
論理演算子: a||b, a&&b, !a
比較演算子: a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b(C++20)
メンバアクセス演算子: a[b], *a, &a, a->b, a.b, a->*b, a.*b
その他の演算子: a(...), a,b, a?b:c
デフォルト比較(C++20)
演算子の代替表現
優先順位と結合性
畳み込み式(C++17)
new 式
delete 式
throw 式
alignof
sizeof
sizeof...(C++11)
typeid
noexcept(C++11)
演算子オーバーロード
変換
暗黙の変換
const_cast
static_cast
reinterpret_cast
dynamic_cast
明示的な変換 (T)a, T(a)
ユーザ定義変換
 
演算子の名前 構文 オーバーロード可能 プロトタイプの例 (class T に対して)
クラス定義の内側 クラス定義の外側
関数呼び出し a(a1, a2) Yes R T::operator()(Arg1 &a1, Arg2 &a2, ... ...); N/A
コンマ a, b Yes T2& T::operator,(T2 &b); T2& operator,(const T &a, T2 &b);
条件演算子 a ? b : c No N/A N/A

目次

[編集] 説明

関数呼び出し演算子は任意のオブジェクトに対し���関数のセマンティクスを提供します。

条件演算子 (俗に三項演算子とも呼ばれます) は、1つめの式のブーリアン値を調べて、その結果の値によって、2つめまたは3つめの式を評価して返します。

[編集] 組み込みの関数呼び出し演算子

関数呼び出し式は以下の形式を持ちます。

E ( A1, A2, A3,... )

ただし

  • E関数を表す式です。
  • A1, A2, A3,... は任意の式のリストです。 空でも構いません。 ただし、曖昧さを避けるため、括弧で囲まれていないコンマ演算子を使用することはできません。

関数を表す式は以下のいずれかです。

a) 関数を参照する lvalue 式。
b) 関数へのポインタ。
c) メンバ関数を選択する明示的なクラスメンバアクセス式。
d) 暗黙のクラスメンバアクセス式。 例えば別のメンバ関数内で使用されるメンバ関数名など。

E によって表される関数 (またはメンバ) 名はオーバーロード可能であり、どのオーバーロードを呼ぶかを決定するためにオーバーロード解決のルールが使用されます。

E がメンバ関数を表す場合、それは仮想関数であっても構いません。 その場合、実行時に動的ディスパッチを用いてその関数の最終オーバーライドが呼ばれます。

関数を呼ぶとき、

E および引数として提供される式 A1A2A3、 ... はすべて任意の順序で評価され、お互いに対して配列されません

(C++17未満)

E は式 A1A2A3、 ... およびデフォルト引数 (もしあれば) のそれぞれに対して先行配列されます。 引数の式は任意の順序で評価され、お互いに対して不定に配列されます

(C++17以上)

関数のそれぞれの仮引数は、必要であれば暗黙の変換を行った後の、対応する実引数で初期化されます。 対応する実引数がない場合は、対応するデフォルト引数が使用されます。 それもない場合は、プログラムは ill-formed です。 呼び出しがメンバ関数に対して行われる場合、現在のオブジェクトの this ポインタはその関数によって期待される this ポインタに、明示的なキャストによって行われたかのように、変換されます。 それぞれの仮引数の初期化および破棄は呼び出し元の文脈で発生します。 つまり、例えば、仮引数のコンストラクタが例外を投げた場合、関数内で定義されている例外ハンドラは (たとえ関数 try ブロックであっても) 考慮されません。 関数が可変長引数を持つ場合、その省略記号の部分にマッチするすべての引数にデフォルトの引数昇格が適用されます。 仮引数の生存期間が、その関数から戻ったときに終了するか、囲っている完全式の終わりで終了するかは、処理系定義です。

関数呼び出し式の戻り値の型は、その選択された関数の戻り値の型です。 たとえ実際に呼ばれるオーバーライドした関数が異なる型を返す場合でも、静的バインディングを用いて (virtual キーワードを無視して) 決定されます。 これはオーバーライドした関数が基底の関数によって返される戻り値の型から派生したクラスへのポインタや参照を返すことを許容します。 すなわち、 C++ は共変戻り値型をサポートします。 E がデストラクタを表す場合、戻り値の型は void です。

クラス型 X のオブジェクトが関数に渡されるまたは関数から返されるとき、 X のコピーコンストラクタ、ムーブコンストラクタ、デストラクタがそれぞれトリビアルであるか削除されているかのいずれかであり、 X が少なくともひとつの削除されていないコピーまたはムーブコンストラクタを持つ場合、処理系は関数の引数または戻り値のオブジェクトを保持するための一時オブジェクトを作成することが許されます。

一時オブジェクトは関数の実引数または戻り値から構築され、その関数の仮引数または返されたオブジェクトは一時オブジェクトをコピーするために削除されていないトリビアルなコンストラクタを使用したかのように初期化されます (たとえそのコンストラクタがアクセス可能でなくても、またはオブジェクトのコピーまたはムーブを行うためにオーバーロード解決によって選択されないであろうとも)。

これにより std::complexstd::span などの小さなクラス型のオブジェクトをレジスタで関数に渡したり返したりすることが可能となります。

(C++17以上)

関数呼び出し式の値カテゴリは、その関数が関数への左辺値参照または右辺値参照を返す場合は lvalue であり、その関数がオブジェクトへの右辺値参照を返す場合は xvalue であり、そうでなければ prvalue です。 関数呼び出し式がオブジェクト型の prvalue である場合、それは完全型でなければなりません。 ただし decltype の被演算子として (または decltype の被演算子である組み込みのコンマ演算子式の右の被演算子として) 使用されるときなど、その prvalue が具体化されないとき (C++17以上)は除きます。

関数呼び出し式は値初期化 T()関数スタイルのキャストT(A1)、および一時オブジェクトの直接初期化 T(A1, A2, A3, ...) (ただし T は型名) と構文が似ています。

#include <cstdio>
struct S
{
    int f1(double d) {
        return printf("%f \n", d); // variable argument function call
    }
    int f2() {
        return f1(7); // member function call, same as this->f1()
                      // integer argument converted to double
    }
};
void f() {
   puts("function called"); // function call
}
int main()
{
    f(); // function call
    S s;
    s.f2(); // member function call
}

出力:

function called
7.000000

[編集] 組み込みのコンマ演算子

コンマ演算子式は以下の形式を持ちます。

E1 , E2

コンマ式 E1, E2 において、式 E1 が評価され、その結果が破棄され (クラス型の場合は囲っている完全式の終わりまで破棄されません)、式 E2 の評価が始まる前にその副作用が完了されます (ユーザ定義の operator, は評価順序を保証できないことに注意してください) (C++17未満)

コンマ演算子の結果の型、値、値カテゴリは正確に2つめの被演算子 E2 の型、値、値カテゴリです。 E2 が一時オブジェクト (C++17以上)の場合、式の結果はその一時オブジェクト (C++17以上)です。 E2 がビットフィールドの場合、結果はビットフィールドです。

関数の引数リスト (f(a, b, c)) や初期化子リスト int a[] = {1,2,3} などの様々なコンマ区切りリスト内のコンマは、コンマ演算子ではありません。 そのような文脈でコンマ演算子を使用する必要がある場合は、括弧で囲む必要があります f(a, (n++, n+b), c)

#include <iostream>
int main()
{
    int n = 1;
    int m = (++n, std::cout << "n = " << n << '\n', ++n, 2*n);
    std::cout << "m = " << (++m, m) << '\n';
}

出力:

n = 2
m = 7

[編集] 条件演算子

条件演算子式は以下の形式を持ちます。

E1 ? E2 : E3

条件演算子の1つめに被演算子は bool文脈的に変換されます。 1つめの被演算子の値の評価とすべての副作用がどちらも完了した後、その結果が true であった場合は2つめの被演算子が評価されます。 結果が falseであった場合は3つめの被演算子が評価されます。

条件式 E1 ? E2 : E3 の型と値カテゴリは以下のルールに従って決定されます。

1) E2 または E3 のいずれかが void 型の場合は、以下のいずれかが真でなければならず、そうでなければプログラムは ill-formed です。
1.1) E2 または E3 のいずれか一方 (しかし両方ではない) が throw 式である (括弧で囲っていても構いません)。 条件演算子の結果は他方の式の型および値カテゴリを持ちます。 他方の式がビットフィールドの場合、結果はビットフィールドです。 このような条件演算子は C++14 以前の C++11 constexpr プログラミングでよく使用されていました。
std::string str = 2+2==4 ? "ok" : throw std::logic_error("2+2 != 4");
1.2) E2 および E3 がどちらも void 型である (両方が throw 式である場合も含みます)。 結果は void 型の prvalue です。
2+2==4 ? throw 123 : throw 456;
2) そうでなく、 E2 または E3 が同じ値カテゴリおよびそれぞれ型 cv1 T および cv2 T のビットフィールドの grvalue の場合、被演算子はこの節の残りに対して cv T であるとみなされます。 ただし cv は cv1 と cv2 の和です。
(C++14以上)
3) そうでなく、 E2E3 が異なる型であり、少なくとも一方がクラス型 (cv 修飾されていても構いません) であるか、または、どちらも同じ値カテゴリの grvalue であり、 cv 修飾を除いて同じ型の場合、以下で述べるように、それぞれの被演算子から、他方の被演算子によって決定されるターゲット型への、暗黙の変換のシーケンスの形成が試みられます。 このとき、メンバアクセス、被演算子がビットフィールドかどうか、変換関数が削除されているかどうかは無視されます。 (C++14以上) TX 型の被演算子 X は、以下のように、他方の TY 型の被演算子 Yターゲット型に変換できます。
3.1) Y が lvalue の場合、ターゲット型は TY& であり、その参照は lvalue に直接的に束縛しなければなりません。
3.2) Y が xvalue の場合、ターゲット型は TY&& であり、その参照は直接的に束縛しなければなりません。
3.3) Y が prvalue の場合、または上記の変換シーケンスのいずれも形成できず、 TXTY の少なくとも一方がクラス型 (cv 修飾されていても構いません) の場合、
3.3.1) TXTY が同じクラス型 (cv 修飾は無視します) であり、 TYTX と同じまたはそれ以上に cv 修飾されている場合、ターゲット型は TY です。
3.3.2) そうでなく、 TYTX の基底クラスの場合、ターゲット型は TX の cv 修飾を持つ TY です。
struct A {}; 
struct B : A {}; 
using T = const B; 
A a = true ? A() : T(); // Y = A()、TY = A、X = T()、TX = const B。 ターゲット型 = const A。
3.3.3) そうでなければ、ターゲット型は、左辺値から右辺値、配列からポインタ、関数からポインタへの標準変換を適用した後に Y が持つであろう型です。
3.4) 両方 (E2 から E3 のターゲット型へ、および E3 から E2 のターゲット型へ) のシーケンスが形成でき、またはいずれか一方しか形成できないけれどもその変換シーケンスが曖昧である場合、プログラムは ill-formed です。
3.5) ちょうどひとつの変換シーケンスのみが形成できる場合 (それでもまだ、例えばアクセス違反によって、 ill-formed になる可能性はあります)、変換シーケンスは適用され、その変換された被演算子がこの説明の残り ((4) から) に対して元の被演算子の場所で使用されます。
3.6) 何の変換シーケンスも形成できない場合、この説明の残りに対して被演算子は変更されません。
4) E2 および E3 が同じ型かつ同じ値カテゴリの glvalue の場合、結果はその同じ型および値カテゴリであり、 E2 および E3 の少なくとも一方がビットフィールドであればビットフィールドです。
5) そうでなければ、結果は prvalue です。 E2E3 が同じ型でなく、どちらかがクラス型 (cv 修飾されていても構いません) の場合、被演算子を組み込みの型に変換することを試みるために下記の組み込みの候補を使用してオーバーロード解決が行われます。 このオーバーロード解決が失敗した場合、プログラムは ill-formed です。 そうでなければ、選択された変換が適用され、変換された被演算子がステップ6に対して元の値の場所で使用されます。
6) 左辺値から右辺値、配列からポインタ、関数からポインタへの変換が2つめおよび3うめの被演算子に適用されます。 その後、
6.1) E2E3 が今や同じ型である場合、結果は、 E1 の評価後に選択されたいずれかの被演算子からコピー初期化された一時オブジェクトを指す (C++17未満)オブジェクトを結果に持つ (C++17以上)、その型の pvalue です。
6.2) E2E3 がどちらも算術型または列挙型である場合、共通の型を得るために通常の算術変換が適用され、その型が結果です。
6.3) E2E3 がどちらもポインタの場合、または一方がポインタで他方がヌルポインタ定数の場合、共通の型を得るためにポインタ変換および修飾子変換が適用され、その型が結果です。
6.4) E2E3 がどちらもメンバポインタである場合、または一方がメンバポインタで他方がヌルポインタ定数の場合、共通の型を得るためにメンバポインタ変換および修飾子変換が適用され、その型が結果です。
6.5) E2E3 がどちらもヌルポインタ定数であり、少なくとも一方が std::nullptr_t 型の場合、結果の型は std::nullptr_t です。
6.6) それ以外のすべての場合において、プログラムは ill-formed です。

昇格された算術型 L および R のすべての組について、およびポインタ、メンバポインタ、またはスコープ付き列挙型であるすべての型 P について、以下の関数シグネチャが上記のルールのステップ5で行われるオーバーロード解決に参加します。

LR operator?:(bool, L, R );
P operator?:(bool, P, P );

ただし LR は LR に行われる通常の算術変換の結果です。 演算子「?:」はオーバーロードできす、これらの関数シグネチャはオーバーロード解決の目的のためにのみ存在しています。

条件演算子の戻り値の型は二項型特性 std::common_type としてもアクセス可能です。

#include <string>
#include <iostream>
struct Node
{
    Node* next;
    int data;
    // deep-copying copy constructor
    Node(const Node& other)
      : next(other.next ? new Node(*other.next) : NULL)
      , data(other.data)
    {}
    Node(int d) : next(NULL), data(d) {}
    ~Node() { delete next ; }
};
int main()
{   
    // simple rvalue example
    int n = 1>2 ? 10 : 11;  // 1>2 is false, so n = 11
    // simple lvalue example
    int m = 10; 
    (n == m ? n : m) = 7; // n == m is false, so m = 7
    std::cout << "n = " << n << "\nm = " << m; //output the result
}

出力:

n = 11
m = 7

[編集] 標準ライブラリ

標準ライブラリの多くのクラスが関数オブジェクトとして使用するために operator() をオーバーロードしています。

オブジェクトまたは配列を削除します
(std::default_delete<T>のパブリックメンバ関数) [edit]
2つの引数の和を返します
(std::plus<T>のパブリックメンバ関数) [edit]
2つの引数の差を返します
(std::minus<T>のパブリックメンバ関数) [edit]
2つの引数の積を返します
(std::multiplies<T>のパブリックメンバ関数) [edit]
第1引数を第2引数で割った結果を返します
(std::divides<T>のパブリックメンバ関数) [edit]
第1引数を第2引数で割った余りを返します
(std::modulus<T>のパブリックメンバ関数) [edit]
引数の否定を返します
(std::negate<T>のパブリックメンバ関数) [edit]
引数が等しいかどうか調べます
(std::equal_to<T>のパブリックメンバ関数) [edit]
引数が等しくないかどうか調べます
(std::not_equal_to<T>のパブリックメンバ関数) [edit]
第1引数が第2引数より大きいかどうか調べます
(std::greater<T>のパブリックメンバ関数) [edit]
第1引数が第2引数より小さいかどうか調べます
(std::less<T>のパブリックメンバ関数) [edit]
第1引数が第2引数より大きいまたは等しいかどうか調べます
(std::greater_equal<T>のパブリックメンバ関数) [edit]
第1引数が第2引数より小さいまたは等しいかどうか調べます
(std::less_equal<T>のパブリックメンバ関数) [edit]
2つの引数の論理積を返します
(std::logical_and<T>のパブリックメンバ関数) [edit]
2つの引数の論理和を返します
(std::logical_or<T>のパブリックメンバ関数) [edit]
引数の論理否定を返します
(std::logical_not<T>のパブリックメンバ関数) [edit]
2つの引数のビット単位の論理積の結果を返します
(std::bit_and<T>のパブリックメンバ関数) [edit]
2つの引数のビット単位の論理和の結果を返します
(std::bit_or<T>のパブリックメンバ関数) [edit]
2つの引数のビット単位の排他的論理和の結果を返します
(std::bit_xor<T>のパブリックメンバ関数) [edit]
格納されている述語の呼び出しの結果の論理否定を返します
(std::unary_negate<Predicate>のパブリックメンバ関数) [edit]
格納されている述語の呼び出しの結果の論理否定を返します
(std::binary_negate<Predicate>のパブリックメンバ関数) [edit]
格納されている関数を呼びます
(std::reference_wrapper<T>のパブリックメンバ関数) [edit]
ターゲットを呼び出します
(std::function<R(Args...)>のパブリックメンバ関数) [edit]
このロケールの照合ファセットを用いて2つの文字列を辞書的に比較します
(std::localeのパブリックメンバ関数) [edit]
2つの value_type 型の値を比較します
(std::map<Key,T,Compare,Allocator>::value_compareのパブリックメンバ関数) [edit]
2つの value_type 型の値を比較します
(std::multimap<Key,T,Compare,Allocator>::value_compareのパブリックメンバ関数) [edit]
関数を実行します
(std::packaged_task<R(Args...)>のパブリックメンバ関数) [edit]
エンジンの状態を進めて生成された値を返します
(std::linear_congruential_engine<UIntType,a,c,m>のパブリックメンバ関数) [edit]
分布の次の乱数を生成します
(std::uniform_int_distribution<IntType>のパブリックメンバ関数) [edit]

コンマ演算子は標準ライブラリのどのクラスによってもオーバーロードされていません。 boost ライブラリは boost.assign、 boost.spirit などのライブラリで operator, を使用しています。 データベースアクセスライブラリ SOCIoperator, をオーバーロードしています。

[編集] 欠陥報告

以下の動作変更欠陥報告は以前に発行された C++ 標準に遡って適用されました。

DR 適用先 発行時の動作 正しい動作
CWG 1550 C++98 parenthesized throw-expression not allowed in ?: if other operand is non-void parenthesized throw-expressions accepted
CWG 1560 C++98 void operand in ?: caused gratuitous l-to-r conversion on the other operand,
always resulting in rvalue
 ?:with a void can be lvalue
CWG 1932 C++14 same-type bit fields were missing in ?: handled by underlying types
CWG 1895 C++14 unclear if deleted or inaccessible conversion function prevents conversion in ?:,
and conversions from base class to derived class prvalue were not considered
handled like overload resolution

[編集] 関連項目

演算子の優先順位

演算子オーバーロード

一般的な演算子
代入 インクリメント
デクリメント
算術 論理 比較 メンバアクセス その他

a = b
a += b
a -= b
a *= b
a /= b
a %= b
a &= b
a |= b
a ^= b
a <<= b
a >>= b

++a
--a
a++
a--

+a
-a
a + b
a - b
a * b
a / b
a % b
~a
a & b
a | b
a ^ b
a << b
a >> b

!a
a && b
a || b

a == b
a != b
a < b
a > b
a <= b
a >= b
a <=> b

a[b]
*a
&a
a->b
a.b
a->*b
a.*b

a(...)
a, b
? :

特殊な演算子

static_cast は型を別の関連する型に変換します。
dynamic_cast は継承階層内で変換します。
const_castcv 修飾子を追加または削除します。
reinterpret_cast は型を無関係の型に変換します。
C スタイルのキャストstatic_cast, const_cast, reinterpret_cast の混合によって型を別の型に変換します。
new は動的記憶域期間を持つオブジェクトを作成します。
delete は以前に new 式によって作成されたオブジェクトを破棄し、取得したメモリ領域を解放します。
sizeof は型のサイズを照会します。
sizeof...パラメータパックのサイズを照会します。 (C++11以上)
typeid は型の型情報を照会します。
noexcept は式が例外を投げることができるかどうかを調べます。 (C++11以上)
alignof は型のアライメント要件を照会します。 (C++11以上)

その他の演算子C言語リファレンス