名前空間
変種
操作

メンバアクセス演算子

提供: 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[b] Yes R& T::operator[](S b); N/A
間接参照 *a Yes R& T::operator*(); R& operator*(T a);
アドレス取得 &a Yes R* T::operator&(); R* operator&(T a);
オブジェクトのメンバ a.b No N/A N/A
ポインタのメンバ a->b Yes R* T::operator->(); N/A
オブジェクトのメンバへのポインタ a.*b No N/A N/A
ポインタのメンバへのポインタ a->*b Yes R& T::operator->*(S b); R& operator->*(T a, S b);
ノート
  • ほとんどのユーザ定義オーバーロードと同様に、戻り値の型はユーザ定義の演算子を組み込みのものと同じ方法で使用できるように、組み込みの演算子によって提供される戻り値の型と一致させるべきです。 しかしユーザ定義の演算子オーバーロードでは任意の型 (void を含む) を戻り値の型として使用できます。 ひとつの例外は operator-> であり、これは現実的に使用可能であるためにはポインタかオーバーロードされた operator-> を持つ別のクラスを返さなければなりません。

目次

[編集] 説明

組み込みの添字演算子はポインタまたは配列の被演算子が指す先のオブジェクトへのアクセスを提供します。

組み込みの間接参照演算子はポインタの被演算子が指す先のポインタまたは関数へのアクセスを提供します。

組み込みのアドレス取得演算子はオブジェクトまたは関数の被演算子を指すポインタを作成します。

オブジェクトのメンバおよびオブジェクトのメンバへのポインタ演算子はオブジェクトの被演算子のデータメンバまたはメンバ関数へのアクセスを提供します。

組み込みのポインタのメンバおよびポインタのメンバへのポインタ演算子はポインタの被演算子が指す先のクラスのデータメンバまたはメンバ関数へのアクセスを提供します。

[編集] 組み込みの添字演算子

添字演算子式は以下の形式を持ちます。

expr1 [ expr2 ] (1)
expr1 [ { expr, ... } ] (2) (C++11)
1) 組み込みの演算子の場合、式の片方 (expr1 または expr2 のどちらか) は「T の配列」型の glvalue または「T へのポインタ」型の prvalue でなければならず、もう片方の式 (expr2 または expr1) はスコープなし列挙型または整数型の prvalue でなければなりません。 この式の結果は T 型です。
2) 角括弧内の波括弧で囲まれたリストを持つ形式はオーバーロードされた operator[] を呼ぶためにのみ使用できます。

組み込みの添字式 E1[E2]評価順序を除いて (C++17以上)*(E1 + E2) と正確に同一です。 つまり、そのポインタの被演算子 (配列からポインタへの変換の結果かもしれません) (何らかの配列の要素またはその最後の次を指していなければなりません) はポインタ算術のルールに従って同じ配列の別の要素を指すように調節され、そして逆参照されます。

配列に適用したとき、添字式は lvalue (その配列が lvalue の場合) または xvalue (そうでない場合) (C++11以上) です。

ポインタに適用したとき、添字式は常に lvalue です。

たとえ &x[0] のようにサイズや内部構造が使用されなくとも、型 T不完全型であることは許されていません。

ユーザ定義に演算子に対するオーバーロード解決において、すべてのオブジェクト型 (およびその cv 修飾された型) T について、以下の関数シグネチャがオーバーロード解決に参加します。

T& operator[](T*, std::ptrdiff_t);
T& operator[](std::ptrdiff_t, T*);
#include <iostream>
 
int main()
{
    int a[4] = {1, 2, 3, 4};
    int* p = &a[2];
    std::cout << p[1] << p[-1] << 1[p] << (-1)[p] << '\n';
}

出力:

4242

[編集] 組み込みの間接参照演算子

間接参照演算子式は以下の形式を持ちます。

* expr

組み込みの間接参照演算子の被演算子はオブジェクトへのポインタまたは関数へのポインタでなければならず、結果は expr が指す先のポインタまたは関数を参照する lvalue です。

void (または cv 修飾された void) へのポインタは逆参照できません。 それ以外の不完全型へのポインタは逆参照できますが、結果の lvalue は不完全型の lvalue が許容される文脈 (参照を初期化するときなど) でのみ使用できます。

ユーザ定義の演算子に対するオーバーロード解決において、オブジェクト型 (またはその cv 修飾された型) または関数型 (const 修飾も ref 修飾もされていない) であるすべての型 T について、以下の関数シグネチャがオーバーロード解決に参加します。

T& operator*(T*);
#include <iostream>
 
int f() { return 42; }
 
int main()
{
    int n = 1;
    int* pn = &n;
 
    int& r = *pn;  // 左辺値は参照に束縛できます
    int m = *pn;   // 間接参照+左辺値から右辺値への変換
 
    int (*fp)() = &f;
    int (&fr)() = *fp; // 関数左辺値は参照に束縛できます
}


[編集] 組み込みのアドレス取得演算子

アドレス取得演算子式は以下の形式を持ちます。

& expr (1)
& class :: member (2)
1) 被演算子が何らかのオブジェクトまたは関数型 T の lvalue 式である場合、 operator& は、その被演算子が表すオブジェクトまたは関数を指す、同じ cv 修飾を持つ T* 型の prvalue を、作成して返します。 被演算子が不完全型の場合、ポインタは形成できますが、その不完全型がたまたま独自の operator& を定義するクラスであった場合、動作は未定義です (C++14未満)組み込みとオーバーロードのどちらが使用されるかは未規定です (C++14以上)。 ユーザ定義の operator& を持つ型の被演算子に対して真のポインタを取得するために std::addressof を使用することができます。 C99 以上の C と異なり、単項 operator* の結果に単項 operator& を適用した場合に対する特別扱いはありません。
被演算子がオーバーロードされた関数の名前である場合、そのオーバーロードが文脈によって解決可能である場合にのみアドレスを取得できます。 詳細はオーバーロードされた関数のアドレスを参照してください。
2) 被演算子が非静的メンバの修飾名 (例えば &C::member) の場合、結果はクラス C の型 Tメンバ関数へのポインタまたはデータメンバへのポインタの prvalue です。 メンバへのポインタを初期化するためには、 &member も、 C::member も、 &(C::member) でさえも、使用できないことに注意してください。

ユーザ定義の演算子に対するオーバーロード解決において、この演算子はいかなる追加の関数シグネチャも導入しません。 適用可能なオーバーロードされた operator& が存在する場合、組み込みのアドレス取得演算子は適用されません。

void f(int) {}
void f(double) {}
struct A { int i; };
struct B { void f(); };
 
int main()
{
    int n = 1;
    int* pn = &n; // ポインタ
    int* pn2 = &*pn; // pn2 == pn
    int A::* mp = &A::i; // データメンバへのポインタ
    void (B::*mpf)() = &B::f; // メンバ関数へのポインタ
 
    void (*pf)(int) = &f; // 初期化の文脈によるオーバーロード解決
//  auto pf2 = &f; // エラー、オーバーロードされた関数の曖昧な型
    auto pf2 = static_cast<void (*)(int)>(&f); // キャストによるオーバーロード解決
}


[編集] 組み込みのメンバアクセス演算子

メンバアクセス演算子式は以下の形式を持ちます。

expr . template(オプション) id-expr (1)
expr -> template(オプション) id-expr (2)
expr . pseudo-destructor (3)
expr -> pseudo-destructor (4)
1) 1つめの被演算子は完全クラス型 T の式でなければなりません。
2) 1つめの被演算子は完全クラス型へのポインタ T* の式でなければなりません。
3,4) 1つめの被演算子はスカラー型の式でなければなりません (下記参照)。

どちらの演算子も1つめの被演算子はたとえ必要でなくとも評価されます (2つめの被演算子が静的メンバを表すときなど)。

どちらの演算子も2つめの被演算子は T の、または T の曖昧でないアクセス可能な基底クラス B の、データメンバまたはメンバ関数の名前 (形式的には、それらを表す識別子式) です (E1.E2E1->E2 など)。 修飾付きであったり (E1.B::E2E1->B::E2 など)、template 曖昧性解消子を使用することもあります (E1.template E2E1->template E2 など)。

ユーザ定義の operator-> が提供される場合、プレーンなポインタを返す operator-> に到達するまで、その戻り値に対して operator-> が再び、再帰的に呼ばれます。

E1->E2 は組み込み型については (*E1).E2 と正確に同等です。 そのため以下のルールでは E1.E2 についてのみ述べます。

E1.E2 において、

1) E2静的データメンバの場合、
  • E2 が参照型 T& または T&& であれば、結果は E2 の参照先のオブジェクトまたは関数を指す T 型の lvalue です。
  • そうでなければ、結果はその静的データメンバを指す lvalue です。
本質的に、どちらの場合も E1 は評価され破棄されます。
2) E2非静的データメンバの場合、
  • E2 が参照型 T& または T&& であれば、結果は E2 の参照先のオブジェクトまたは関数を指す T 型の lvalue です。
  • そうでなく、 E1 が lvalue であれば、結果は E1 のその非静的データメンバを指す lvalue です。
  • そうでなければ (E1rvalue (C++17未満)xvalue (prvalue から具体化されたものかもしれません) (C++17以上) であれば)、結果は E1 のその非静的データメンバを指す rvalue (C++11未満)xvalue (C++11以上) です。
E2 が mutable なメンバでない場合、結果の cv 修飾E1E2 の cv 修飾の和です。 そうでなければ (E2 が mutable なメンバの場合)、 E1E2 の volatile 修飾の和です。
3) E2静的メンバ関数の場合、結果はその静的メンバ関数を指す lvalue です。 本質的にに、この場合 E1 は評価され破棄されます。
4) E2非静的メンバ関数 (デストラクタを含む) の場合、結果はメンバ関数呼び出し演算子の被演算子の左の被演算子としてのみ使用でき他の目的には使用できない、 E1 のその非静的メンバ関数を指す特別な種類の prvalue です。
5) E2 がメンバ列挙子の場合、結果は E1 のそのメンバ列挙子と等しい prvalue です。
6) E2ネストした型の場合、プログラムは ill-formed です (コンパイルできません)。
7) E1スカラー型であり、 E2~ に後続する cv 修飾を除去した同じ型を指す型名 (修飾名でも構いません) または decltype 指定子である場合、結果は関数呼び出し演算子の左側の被演算子としてのみ使用でき他の目的には使用できない、特別な種類の prvalue です。 結果の関数呼び出し式は疑似デストラクタ呼び出しと呼ばれます。 引数を取らず、 void を返し、最初の E1 の評価以外は何も行いません。 これは operator. の左側の被演算子が非クラス型である唯一のケースです。 疑似デストラクタ呼び出しを許容することにより与えられた型にデストラクタが存在するかどうかを知る必要なくコードを書くことができます。

operator. はオーバーロードできません。 operator-> については、ユーザ定義の演算子に対するオーバーロード解決において、組み込みの演算子はいかなる追加の関数シグネチャも導入しません。 適用可能なオーバーロードされた operator-> が存在する場合、組み込みの operator-> は適用されません。

#include <iostream>
 
struct P
{
    template<typename T>
    static T* ptr() { return new T; }
};
 
template<typename T>
struct A
{
    A(int n): n(n) {}
    int n;
    static int sn;
    int f() { return 10 + n; }
    static int sf() { return 4; }
    class B {};
    enum E {RED = 1, BLUE = 2};
 
    void g()
    {
        typedef int U;
        // 依存テンプレートメンバのためキーワード template が必要です
        int* p = T().template ptr<U>();
        p->~U(); // U は int であり、 int の疑似デストラクタを呼びます
        delete p;
    }
};
template<> int A<P>::sn = 2;
 
int main()
{
    A<P> a(1);
    std::cout << a.n << ' '
              << a.sn << ' '   // a.A::sn でも構いません
              << a.f() << ' ' 
              << a.sf() << ' ' // a.A::sf() でも構いません
//            << a.B << ' '    // エラー、ネストした型は使用できません
              << a.RED << ' '; // 列挙子
}

出力:

1 2 11 4 1

[編集] 組み込みのメンバポインタアクセス演算子

メンバへのポインタを通したメンバアクセス演算子式は以下の形式を持ちます。

lhs .* rhs (1)
lhs ->* rhs (2)
1) lhs はクラス型 T の式でなければなりません。
2) lhs はクラス型へのポインタ型 T* の式でなければなりません。

どちらの演算子も2つめの被演算子は T のメンバ (データメンバまたはメンバ関数) へのポインタ型または T の曖昧でないアクセス可能な基底クラス B のメンバへのポインタ型の式です。

E1->*E2 は組み込み型の場合 (*E1).*E2 と正確に同等です。 このため以下のルールでは E1.*E2 についてのみ述べます。

E1.*E2 において、

1) E2 がデータメンバへのポインタの場合、
  • E1 が lvalue であれば、結果はそのデータメンバを指す lvalue です。
  • そうでなければ (E1rvalue (C++17未満)xvalue (prvalue から具体化されたものかもしれません) (C++17以上) であれば)、結果はそのデータメンバを指す rvalue (C++11未満)xvalue (C++11以上) です。
2) E2 がメンバ関数へのポインタの場合、結果はメンバ関数呼び出し演算子の左側の被演算子としてのみ使用でき他の目的には使用できない、メンバ関数を指す特別な種類の prvalue です。
3) cv 修飾のルールはオブジェクトのメンバの演算子と同じですが、追加のルールがひとつあります。 mutable メンバを参照するメンバへのポインタを const オブジェクト内のそのメンバを変更するために使用することはできません。
4) E2 がメンバへのヌルポインタ値の場合、動作は未定義です。
5) E1動的な型E2 の参照先のメンバを持たない場合、動作は未定義です。
6) E1 が rvalue であり、 E2 が ref 修飾子 & を持つメンバ関数を指す場合、そのメンバ関数も const 修飾されているけれども volatile 修飾されていない場合を除いて (C++20以上)プログラムは ill-formed です。
7) E1 が lvalue であり、 E2 が ref 修飾子 && を持つメンバ関数を指す場合、プログラムは ill-formed です。

ユーザ定義の演算子に対するオーバーロード解決において、クラス型 BD と同じクラスであるか D の曖昧でなくアクセス可能な基底クラスであり、 R がオブジェクト型または関数型であるような、型 DBR のすべての組み合わせについて、以下の関数シグネチャがオーバーロード解決に参加します。

R& operator->*(D*, R B::*);

ただし、どちらの被演算子も cv 修飾されていても良く、その場合、戻り値の型の cv 修飾は被演算子の cv 修飾の和です。

#include <iostream>
 
struct S
{
    S(int n): mi(n) {}
    mutable int mi;
    int f(int n) { return mi + n; }
};
 
struct D: public S
{
    D(int n): S(n) {}
};
 
int main()
{
    int S::* pmi = &S::mi;
    int (S::* pf)(int) = &S::f;
 
    const S s(7);
//  s.*pmi = 10; // エラー、 mutable を通して変更することはできません
    std::cout << s.*pmi << '\n';
 
    D d(7); // 基底クラスのポインタを派生オブジェクトで使用できます
    D* pd = &d;
    std::cout << (d.*pf)(7) << ' '
              << (pd->*pf)(8) << '\n';
}

出力:

7
14 15

[編集] 標準ライブラリ

添字演算子は多くの標準のコンテナクラスでオーバーロードされています。

特定のビットにアクセスします
(std::bitset<N>のパブリックメンバ関数) [edit]
管理対象配列へのインデックスアクセスを提供します
(std::unique_ptr<T,Deleter>のパブリックメンバ関数) [edit]
指定された文字にアクセスします
(std::basic_string<CharT,Traits,Allocator>のパブリックメンバ関数) [edit]
指定された要素にアクセスします
(std::array<T,N>のパブリックメンバ関数) [edit]
指定された要素にアクセスします
(std::deque<T,Allocator>のパブリックメンバ関数) [edit]
指定された要素にアクセスします
(std::vector<T,Allocator>のパブリックメンバ関数) [edit]
指定された要素にアクセスまたは挿入します
(std::map<Key,T,Compare,Allocator>のパブリックメンバ関数) [edit]
指定された要素にアクセスまたは挿入します
(std::unordered_map<Key,T,Hash,KeyEqual,Allocator>のパブリックメンバ関数) [edit]
インデックスによって要素にアクセスします
(std::reverse_iterator<Iter>のパブリックメンバ関数) [edit]
インデックスによって要素にアクセスします
(std::move_iterator<Iter>のパブリックメンバ関数) [edit]
valarray の要素、スライス、マスクを取得または設定します
(std::valarray<T>のパブリックメンバ関数) [edit]
指定された部分マッチを返します
(std::match_results<BidirIt,Alloc>のパブリックメンバ関数) [edit]

間接参照およびメンバ演算子は多くのイテレータやスマートポインタクラスでオーバーロードされています。

管理対象オブジェクトへのポインタを逆参照します
(std::unique_ptr<T,Deleter>のパブリックメンバ関数) [edit]
格納されているポインタを逆参照します
(std::shared_ptr<T>のパブリックメンバ関数) [edit]
管理対象オブジェクトにアクセスします
(std::auto_ptr<T>のパブリックメンバ関数) [edit]
イテレータを逆参照します
(std::raw_storage_iterator<OutputIt,T>のパブリックメンバ関数) [edit]
デクリメントしたベースとなるイテレータを逆参照します
(std::reverse_iterator<Iter>のパブリックメンバ関数) [edit]
何もしません
(std::back_insert_iterator<Container>のパブリックメンバ関数) [edit]
何もしません
(std::front_insert_iterator<Container>のパブリックメンバ関数) [edit]
何もしません
(std::insert_iterator<Container>のパブリックメンバ関数) [edit]
(C++20で非推奨)
イテレータの指す先の要素にアクセスします
(std::move_iterator<Iter>のパブリックメンバ関数) [edit]
現在の要素を返します
(std::istream_iterator<T,CharT,Traits,Distance>のパブリックメンバ関数) [edit]
何もしません
(std::ostream_iterator<T,CharT,Traits>のパブリックメンバ関数) [edit]
(C++11以上)(C++17未満)
現在の文字のコピーを取得します
CharT がメンバを持つ場合、現在の文字のメンバにアクセスします
(std::istreambuf_iterator<CharT,Traits>のパブリックメンバ関数) [edit]
何もしません
(std::ostreambuf_iterator<CharT,Traits>のパブリックメンバ関数) [edit]
現在のマッチにアクセスします
(std::regex_iterator<BidirIt,CharT,Traits>のパブリックメンバ関数) [edit]
現在の部分マッチにアクセスします
(std::regex_token_iterator<BidirIt,CharT,Traits>のパブリックメンバ関数) [edit]

operator& をオーバーロードする標準ライブラリのクラスはありません。 operator& のオーバーロードの最も知られている例は Microsoft COM のクラス CComPtr です。 また boost.spirit などの EDSL でも見ることができます。

operator->* をオーバーロードする標準ライブラリのクラスはありません。 スマートポインタのインタフェースの一部となることが提案され、実際 boost.phoenix のアクタによってその用途で使用されていますが、 cpp.react などの EDSL で使用される方がより一般的です。

[編集] 欠陥報告

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

DR 適用先 発行時の動作 正しい動作
CWG 1213 C++11 subscripting an array rvalue resulted in lvalue reclassified as xvalue

[編集] 関連項目

演算子の優先順位

演算子オーバーロード

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

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言語リファレンス