Member access operators - cppreference.com

##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# Member access operators

From cppreference.com
< cpp‎ | language

Accesses a member of an object.

Operator name | Syntax | Over​load​able | Prototype examples (for class T)
--- | --- | --- | ---
Inside class definition | Outside class definition
array subscript | `a[b]` | Yes | R& T::operator[](const T2& b); | N/A
indirection (variable pointed to by `a`) | `*a` | Yes | R& T::operator*(); | R& operator*(T &a);
address of | `&a` | Yes | R* T::operator&(); | R* operator&(T &a);
member of object | `a.b` | No | N/A | N/A
member of pointer | `a->b` | Yes | R* T::operator->() | N/A
pointer to member of object | `a.*b` | No | N/A | N/A
pointer to member of pointer | `a->*b` | Yes | R* T::operator->*(R) | R* T::operator->*(T, R)
Notes As with most user-defined overloads, return types should match return types provided by the builtin operators so that the user-defined operators can be used in the same manner as the built-ins. However, in a user-defined operator overload, any type can be used as return type (including void). One exception is `operator->`, which must return a pointer or another class with overloaded `operator->`.

### [edit] Explanation

array subscript operator provides access to the elements in the internal array

indirection, member of pointer and pointer to member of pointer operators provide pointer semantics for any object.

member of pointer and pointer to member of pointer operators return a pointer to the actual object which will be used for member access.

#### [edit] Built-in subscript operator

For every object type `T` (possibly cv-qualified), the following function signature participates in overload resolution:

T& operator[](T*, std::ptrdiff_t); |  |
T& operator[](std::ptrdiff_t, T*); |  |

The non-pointer operand may be any expression of integral or unscoped enumeration type, it is implicitly converted to std::ptrdiff_t. The expression A[B] is exactly identical to the expression *(A+B), that is, the pointer operand (which may be a result of array-to-pointer conversion, and which must point to an element of some array or one past the end) is adjusted to point at another element of the same array, following the rules of pointer arithmetics, and is then dereferenced.

When applied to an array, the subscript expression is an lvalue if the array is an lvalue, and xvalue if it isn't. When applied to a pointer, the subscript expression is always lvalue.

The type `T` is not allowed to be an incomplete type, even if the size or internal structure of `T` is never used, as in &x[0].

Run this code

    #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';
    }

Output:

    4242

#### [edit] Built-in indirection operator

For every type `T` that is either object type (possibly cv-qualified) or function type (not const- or ref-qualified), the following function signature participates in overload resolution:

T& operator*(T*); |  |

The operand of the built-in indirection operator is a pointer to object or function, and the result is the lvalue that the pointer is pointing at. Note that a pointer to incomplete type can be dereferenced, e.g. when initializing a reference.

Run this code

    #include <iostream>
    int f() { return 42; }
    int main()
    {
        int n = 1;
        int* pn = &n;

        int& r = *pn;  // lvalue can be bound to a reference
        int m = *pn;   // indirection + lvalue-to-rvalue conversion

        int (*fp)() = &f;
        int (&fr)() = *fp; // function lvalue can be bound to a reference
    }

#### [edit] Built-in address-of operator

The operand of the built-in `operator&` is either an lvalue expression of any type or the qualified name of a non-static member function/object in some class. This operator does not participate in overload resolution. If there are no viable functions, special rules are used:

If the operand is an lvalue expression of some type `T`, `operator&` creates and returns a prvalue of type `T*`, with the same cv qualification, that is pointing at the object designated by the operand. If the operand has incomplete type, the pointer can be formed, but if that incomplete type happens to be a class that defines its own `operator&`, the behavior is undefined (until C++14) it is unspecified whether the built-in or the overload is used (since C++14). For the operands of type with user-defined `operator&`, std::addressof may be used to obtain the true pointer.

If the operand is the name of an overloaded function, the address may be taken only if the overload can be resolved due to context. See Address of an overloaded function for details.

If the operand is a qualified name of a non-static member, e.g. &Class::member, the result is a prvalue pointer to member function or pointer to member object of type `T` in class `C`. Note that neither &member nor Class::member nor even &(Class::member) may be used to initialize a pointer to member.

Run this code

    void f(int) {}
    void f(double) {}
    struct A { int i; };
    struct B { void f(); };
    int main()
    {
        int n = 1;
        int* pn = &n; // pointer
        int A::* mp = &A::i;  // pointer to member object
        void (B::*mpf)() = &B::f; // pointer to member function

    //    auto pf2 = &f; // error: ambiguous overloaded function type
        void (*pf)(int) = &f; // overload resolution due to initialization
        auto pf2 = static_cast<void(*)(int)>(&f); // overload resolution due to cast
    }

#### [edit] Built-in member access operators

The left operand of the built-in `operator.` and `operator->` is an expression of complete scalar type `T` (for `operator.`) or pointer to complete scalar type `T*` (for `operator->`), which is evaluated before the operator can be called. The right operand is the name of a member object or member function of `T` or of one of `T`'s base classes, e.g. expr.member, optionally qualified, e.g. expr.name::member, optionally using template disambiguator, e.g. expr.template member.

The expression A->B is exactly equivalent to (*A).B for builtin types. If a user-defined `operator->` is provided, `operator->` is called again on the value that it returns, recursively, until the `operator->` is reached that returns a plain pointer. After that, builtin semantics are applied to that pointer.

In the expression expr.B,

1) if `B` is a static data member of type `T`, the result is an lvalue `T` designating that static data member.
2) if `B` is a non-static data member of type `T`, the result is an lvalue of type `T` if `B` has type T& or T&&, otherwise the result is an lvalue if `expr` is an lvalue, or the result is a xvalue if `expr` is an rvalue. If `B` is not declared to be a mutable member, the cv-qualification of the result is the union of cv-qualifications of `expr` and `B`. If `B` is mutable, the cv-qualification of the result is the union of volatile-qualifications.
3) if `B` is a static member function, the result is an lvalue designating the static memeber function. Essentially, `expr` is evaluated and discarded in this case.
4) if `B` is a non-static member function including a destructor, the result is a special kind of prvalue that can only be used as the left-hand operand in a function-call expression, and for no other purpose.
5) if `B` is a member enumeration, the result is a prvalue of the enum type.
6) if `B` is a nested type, the program is ill-formed (won't compile)
7) if `expr` has non-class scalar type and B is a `~` followed by the type name or decltype specifier designating the same type (minus cv-qualifications), optionally qualified, then the result is a special kind of prvalue that can only be used as the left-hand operand in a function-call expression, and for no other purpose. The function call is called pseudo destructor call, it takes no arguments, returns void, and performs no action other than initial evaluation of expr.
This is the only case where the left operand of `operator.` has non-class type. Allowing pseudo destructor call makes it possible to write code without having to know if a destructor exists for a given type.
Run this code

    #include <iostream>

    struct P {
        template<typename T>
        static T* ptr() noexcept {return new T;}
    };
    template<typename T>
    struct A {
        class B {};
        enum E {RED = 1, BLUE = 2};
        int n;
        static int sn;
        int f() { return 10+n; }
        static int fs() { return 4; }
        A(int n) : n(n) {}

        // keyword template needed to refer to a dependent template member
        void g() {
            typedef int U;
            int* p = T().template ptr<U>();
            p->~U(); // U is int, this calls int's pseudo destructor
            delete p;
        }
    };
    template<> int A<P>::sn = 2;

    int main()
    {
        A<P> a(1);
        std::cout << a.n << ' '
                  << a.sn << ' ' // << A::sn also works
                  << a.f() << ' '
                  << a.fs() << ' ' // A::fs() also works
                  << a.RED << ' '  // enumerator
    //            << a.B  // nested type not allowed
                  ;
    }

Output:

    1 2 11 4 1

#### [edit] Built-in pointer-to-member access operators

The right operand of both `operator.*` and `operator->*` is an expression of type pointer to member in class `T`. For `operator.*`, the left operand is an expression of class type `T`, or of some derived class in which `T` is unambiguous accessible base. For `operator->*`, the left operand is a pointer to `T` or to its base.

For every combination of types `B`, `D`, `T`, where `D` is either the same as `B` or a class derived from `B`, and `T` is either object or function type, the following function signature participates in overload resolution:

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

where both operands may be cv-qualified, in which case the return type's cv-qualification is the union of the cv-qualification of the operands.

The expression E1->*E2 is exactly equivalent to (*E1).*E2 for built-in types.

For the expression expr.*ptr,

1) If the dynamic type of `expr` does not contain the member to which `ptr` refers, the behavior is undefined
2) cv-qualification rules are the same as for member access operator, with one additional rule: a pointer to member that refers to a mutable member cannot be used to modify that member in a const object.
4) If `expr` is rvalue and `ptr` points to a member function with & ref-qualifier, the program is ill-formed
5) If `expr` is lvalue and `ptr` points to a member function with && ref-qualifier, the program is ill-formed
6) The result of expr.*ptr where `ptr` is a pointer to data member has the same value category as `expr`.
7) The result of expr.*ptr where `ptr` is a pointer to member function is a special kind of prvalue that may only be used as the left-hand argument of a function call expression and for no other purpose.
8) If `ptr` is a null pointer value, the behavior is undefined
Run this code

    #include <iostream>
    struct S
    {
        mutable int mi;
        int f(int n) { return mi+n; }
        S(int n) : mi(n) {}
    };
    struct D : public S {
            D(int n) : S(n) {}
    };

    int main()
    {
        int S::* pmi = &S::mi;
        int (S::*mpf)(int) = &S::f;

        const S s(7);
    //    s.*pmi = 10; // cannot modify through mutable
        std::cout << s.*pmi << '\n';

        D d(7); // base pointers work with derived object
        D* dp = &d;
        std::cout << (d.*mpf)(7) << ' '
                  << (dp->*mpf)(8) << '\n';
    }

Output:

    7
    14 15

### [edit] Standard library

Subscript operator is overloaded by many standard container classes

operator[] | accesses specific bit (public member function of `std::bitset`) [edit]
operator[] | provides indexed access to the managed array (public member function of `std::unique_ptr`) [edit]
operator[] | access specified character (public member function of `std::basic_string`) [edit]
operator[] | access specified element (public member function of `std::array`) [edit]
operator[] | access specified element (public member function of `std::deque`) [edit]
operator[] | access specified element (public member function of `std::vector`) [edit]
operator[] | access specified element (public member function of `std::map`) [edit]
operator[] | access specified element (public member function of `std::unordered_map`) [edit]
operator[] | accesses an element by index (public member function of `std::reverse_iterator`) [edit]
operator[] | accesses an element by index (public member function of `std::move_iterator`) [edit]
operator[] | get/set valarray element, slice, or mask (public member function of `std::valarray`) [edit]
operator[] | returns specified sub-match (public member function of `std::match_results`) [edit]

The indirection and member access operators are overloaded by many iterators and smart pointer classes

operator*operator-> | dereferences pointer to the managed object (public member function of `std::unique_ptr`) [edit]
operator*operator-> | dereferences pointer to the managed object (public member function of `std::shared_ptr`) [edit]
operator*operator-> | accesses the managed object (public member function of `std::auto_ptr`) [edit]
operator* | dereferences the iterator (public member function of `std::raw_storage_iterator`) [edit]
operator*operator-> | dereferences the decremented underlying iterator (public member function of `std::reverse_iterator`) [edit]
operator* | no-op (public member function of `std::back_insert_iterator`) [edit]
operator* | no-op (public member function of `std::front_insert_iterator`) [edit]
operator* | no-op (public member function of `std::insert_iterator`) [edit]
operator*operator-> | accesses the pointed-to element (public member function of `std::move_iterator`) [edit]
operator*operator-> | returns the current element (public member function of `std::istream_iterator`) [edit]
operator* | no-op (public member function of `std::ostream_iterator`) [edit]
operator*operator-> (since C++11) | obtains a copy of the current character accesses a member of the current character, if `CharT` has members (public member function of `std::istreambuf_iterator`) [edit]
operator* | no-op (public member function of `std::ostreambuf_iterator`) [edit]
operator*operator-> | accesses the current match (public member function of `std::regex_iterator`) [edit]
operator*operator-> | accesses current submatch (public member function of `std::regex_token_iterator`) [edit]
No standard library classes overload `operator&` or `operator->*`. The best known example of overloaded `operator&` is the Microsoft COM class CComPtr. `operator->*` is sometimes overloaded by third-party custom smart pointers.

### [edit] See also

Operator precedence

Common operators
assignment | increment decrement | arithmetic | logical | comparison | member access | other
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 &a a->b a.b a->*b a.*b | a(...) a, b (type) a ? :
Special operators
`static_cast` converts one type to another compatible type `dynamic_cast` converts virtual base class to derived class `const_cast` converts type to compatible type with different cv qualifiers `reinterpret_cast` converts type to incompatible type `new` allocates memory `delete` deallocates memory `sizeof` queries the size of a type `sizeof...` queries the size of a parameter pack (since C++11) `typeid` queries the type information of a type `noexcept` checks if an expression can throw an exception (since C++11) `alignof` queries alignment requirements of a type (since C++11)

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/language/operator_member_access&oldid=72334"