Espacios de nombres
Variantes
Acciones

Operadores de acceso a miembro

De cppreference.com
< cpp‎ | language
 
 
 
Expresiones
General
categorías de valores (lvalue, rvalue, xvalue)
orden de evaluación (puntos de secuencia)
expresiones constantes
Operadores
Operadores de asignación: a=b, a+=b, a-=b, a*=b, a/=b, a%=b, a&=b, a|=b, a^=b, a<<=b, a>>=b
Operadores aritméticos: +a, -a, a+b, a-b, a*b, a/b, a%b, ~a, a&b, a|b, a^b, a<<b, a>>b
Incremento y decremento: ++a, --a, a++, a--
Operadores lógicos: a||b, a&&b, !a
Operadores de comparación: a==b, a!=b, a<b, a>b, a<=b, a>=b, a<=>b(C++20)
Operadores de acceso a miembro: a[b], *a, &a, a->b, a.b, a->*b, a.*b
Otros operadores: a(...), a,b, a?b:c
sizeof
alignof (C++11)
expresión new
expresión delete
typeid
 

Accede a un miembro de su operando (objeto).

Nombre operador Sintaxis Sobrecargable Ejemplos de prototipos (para class T)
Dentro de la definición de clase Fuera de la definición de clase
subíndice a[b] Si R& T::operator[](S b); N/A
indirección *a Si R& T::operator*(); R& operator*(T a);
dirección de &a Si R* T::operator&(); R* operator&(T a);
miembro de objeto a.b No N/A N/A
miembro de puntero a->b Si R* T::operator->(); N/A
puntero a miembro de objeto a.*b No N/A N/A
puntero a miembro de puntero a->*b Si R& T::operator->*(S b); R& operator->*(T a, S b);
Notas
  • Como con muchas sobrecargas definidas por usuario, los tipos de retorno pueden coincidir con los tipos de retorno proporcionados por los operadores integrados, por lo que los operadores definidos por usuario se pueden usar de la misma manera que los integrados. Sin embargo, en una sobrecarga de operador definida por usuario, se pueden utilizar cualquier tipo como tipo de retorno (incluyendo void). Una excepción es operator->, que debe devolver un puntero u otra clase con operator-> sobrecargado para ser realmente útil.

Contenido

[editar] Explicación

El operador subíndice integrado proporciona acceso a un objeto apuntado a través del operando puntero o matriz.

El operador indirección integrado proporciona acceso a un objeto apuntado a través del operando puntero.

El operador dirección de integrado crea un puntero que apunta al operando objeto o función.

Los operadores miembro de objeto y puntero a miembro de objeto proveen acceso a un miembro datos o función de la clase operando.

Los operadores miembro de puntero y puntero a miembro de puntero integrados proveen acceso a un miembro de datos o función de la clase apuntada por el operando puntero.

[editar] Operador subíndice integrado

Las expresiones del operador subíndice tienen la forma

expr1 [ expr2 ] (1)
expr1 [ { expr, ... } ] (2) (C++11)
1) Para el operador integrado, una de las expresiones (expr1 o expr2) debe ser un glvalue de tipo “matriz de T” o un prvalue de tipo “puntero a T”, mientras que la otra expresión (expr2 o expr1, respectivamente) debe ser un prvalue de tipo enumerado sin ámbito o entero. El resultado de esta expresión tiene el tipo T.
2) La forma con una lista dentro de los corchetes se usa solamente para llamar al operator[] sobrecargado.

La expresión subíndice integrada E1[E2] es exactamente identica a la expresión *(E1 + E2) excepto el orden de evaluación (desde C++17), es decir, el operando puntero (que puede ser el resultado de la conversión de matriz a puntero, y que debe apuntar a un elemento de la misma matriz o uno después del final) se justa para apuntar a otro elemento de la misma matriz, siguiendo las reglas de la aritmética de punteros, y luego se desreferencia.

Cuando se aplica a una matriz, la expresión de subíndice es un lvalue si la matriz es un lvalue, y un xvalue si no (desde C++11).

Cuando se aplica a un puntero, la expresión de subíndice siempre es un lvalue.

No se permite que el tipo T sea un tipo incompleto, incluso si el tamaño o la estructura interna de T nunca se usa, como en &x[0].

En la resolución de sobrecarga de operadores definidos por usuario, para cada tipo de objeto T (con posibilidad de calificación constante/volátil), los siguientes modelos de función participan en la resolución de sobrecarga:

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

Salida:

4242

[editar] Operador de indirección integrado

Las expresiones del operador de indirección tienen la forma

* expr

El operando del operador de indirección integrado debe ser un puntero a objeto o puntero a función, y el resultado es el lvalue que se refiere al puntero o función al que apunta expr.

Un puntero a (que puede ser calificado constante/volátil) void no se puede desreferenciar. Los punteros a otros tipos incompletos se pueden desreferenciar, pero el lvalue resultante solamente se puede usar en contextos que permiten un lvalue de tipo incompleto, por ejemplo, cuando se inicia una referencia.


En la resolución de sobrecarga de opradores definidos por usuario, para cada tipo T que es de tipo objeto (que puede ser calificado constante/volátil) o tipo función (no calificada const- o ref-), los siguientes modelos de función participan en la resolución de la sobrecarga:

T& operator*(T*);
#include <iostream>
 
int f() { return 42; }
 
int main()
{
    int n = 1;
    int* pn = &n;
 
    int& r = *pn;  // lvalue puede estar vinculado a una referencia
    int m = *pn;   // indirección + conversión de lvalue a rvalue
 
    int (*fp)() = &f;
    int (&fr)() = *fp; // lvalue función puede estar vinculado a una referencia 
}


[editar] Operador dirección de integrado

Las expresiones del operador dirección de tienen la forma

& expr (1)
& class :: member (2)
1) Si el operando es una expresión lvalue de algun tipo objeto o función T, operator& crea y devuelve un prvalue de tipo T*, con la misma calificación constante/volátil, que apunta al objeto o función designado por el operando. Si el operando tiene tipo incompleto, el puntero se puede crear, pero ese tipo incompleto resulta ser una clase que define su propio operator&, el comportamiento es indeterminado (hasta C++14) no se especifica si se usa el integrado la sobrecarga (desde C++14). Para los operandos de tipo con operator& definido por el usuario, se debe usar std::addressof para obtener el puntero verdadero.
Si el operando es el nombre de una función sobrecargada, la dirección solo se puede obtener si la sobrecarga se puede resolver por el contexto. Vea Dirección de una función sobrecargada para más detalles.
2) Si el operando es un nombre calificado de un miembro no estático, por ejemplo &C::member, el resultado es un prvalue puntero a función miembro o puntero a miembro datos de tipo T en la calse C. Tenga en cuenta que ni &member, ni C::member, ni siquiera &(C::member) pueden utilizarse para inicializar un puntero a miembro.

En la resolución de sobrecarga de operadores definida por usuario, este operador no introduce ningún modelo de función adicional: el operador dirección de integrado no se aplica si existe un operator& sobrecargado que es una función viable.

void f(int) {}
void f(double) {}
struct A { int i; };
struct B { void f(); };
 
int main()
{
    int n = 1;
    int* pn = &n; // puntero
    int* pn2 = &*pn; // pn2 == pn
    int A::* mp = &A::i; // puntero a miembro dato
    void (B::*mpf)() = &B::f; // puntero a miembro función
 
    void (*pf)(int) = &f; // resolución de sobrecarga debido al contexto de incialización
//  auto pf2 = &f; // error: tipo de función sobrecargada ambigua
    auto pf2 = static_cast<void (*)(int)>(&f); // resolución de sobrecarga debido a cast
}


[editar] Operadores de acceso a miembro integrados

Las expresiones del operadores de acceso a miembro tienen la forma

expr . template(opcional) id-expr (1)
expr -> template(opcional) id-expr (2)
expr . pseudo-destructor (3)
expr -> pseudo-destructor (4)
1) El primer operando debe se una expresión de tipo clase completo T.
2) El primer operando debe ser una expresión de puntero a un tipo clase completo T*.
3,4) El primer operando debe se una expresión de tipo escalar (ver más abajo).

El primer operando de ambos operadores se evalúa incluso si no es necesario (por ejemplo, cuando el segundo operando es un miembro estático).

El segundo operando de ambos operadores es un nombre de (formalmente, una expresión id que nombra) un miembro dato o función de T o de una clase base B, no ambigua y accesible, de T (por ejemplo E1.E2 o E1->E2), opcionalmente cualificada (por ejemplo E1.B::E2 o E1->B::E2), opcionalmente utilizando el desambiguador de plantilla (por ejemplo E1.template E2 o E1->template E2).

Si se provee {tt|operator->}} definido por usuario, el operator-> se llama de nuevo sobre el valor de devuelve, recursivamente, hasta que se alcanza un operator-> que devuelve un puntero plano. Después de esto, se aplica la semántica del integrado a este puntero.

La expresión E1->E2 es exactamente equivalente a (*E1).E2 para los tipos integrados; es por eso que las siguientes reglas se refieren solamente a E1.E2.

En la expresión E1.E2:

1) si E2 es un miembro de datos estático:
  • si E2 es de tipo refrencia T& o T&&, el resultado es un lvalue de tipo T que designa el objeto o función a la que refiere E2,
  • en otro caso, el resultado es un lvalue que designa es ese miembro de datos estático.
Esencialmente, E1 se evalúa y descarta en los casos;
2) si E2 es un miembro de datos no estático:
  • si E2 es de tipo referencia T& o T&&, el resultado es un lvalue de tipo T que designa al objeto o función al que se refiere E2,
  • en otro caso, si E1 es un lvalue, el resultado es un lvalue que designa aun miembro no estático de E1,
  • en otro caso, (si E1 es un rvalue (hasta C++17)xvalue (que puede ser creado desde un prvalue) (desde C++17)), el resultado es un rvalue (hasta C++11)xvalue (desde C++11) que designa a un miembro de datos no estático de E1.
Si E2 no es un miembro mutable, la cualificación constante/volátil del resultado es la unión las cualificaciones de E1 y E2, en otro caso (si E2 es un miembro mutable), es la unión de la calificación volátil de E1 y E2;
3) si E2 es una función miembro estática, el resultado es un lvalue que designa esa función miembro estática. Esencialmente, se evalúa y se descarta E1 en este caso;
4) siE2 es una función miembro no estática incluyendo un destructor, el resultado es un tipo especial de prvalue que designa una función miembro no estática de E1 que solamente se puede usar como operando izquierdo del operador de llamada a función miembro, y no para otro proposito;
5) siE2 es un enumerado miembro, el resultado es un prvalue igual al enumerado miembro de E1;
6) siE2 es un tipo anidado, el programa está mal formado (no compila);
7) siE1 tiene un tipo escalar y E2 es un ~ seguido por el nombre de tipo o el especificador decltype designando el mismo tipo (menos las cualificaciones constante/volátil), opcionalmente cualificado, el resultado es un tipo especial de prvalue que solamente puede usarse como operando izquierdo de un operador de llamada a función, y no para otro propósito. La expresión de llamada a función resultante se llama llamada a pseudodestructor. No tiene argumentos, devuelve void, y no realiza otra acción que la evaluación inicial de E1. Este es el único caso donde el operando izquierdo de operator. no tiene tipo de clase. Permitiendo llamada a pseudodestructor se hace posible escribir código sin tener conocimiento si existe destructor para el tipo utilizado.

operator. no se puede sobrecargar, y para operator->, en la resolución de sobrecarga de operadores definida por usuario, el operador integrado no introduce ningún modelo adicional de función: operator-> integrado no se aplica si existe un operator-> sobrecargado que es una función viable.

#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;
        // es necesaria la palabra reservada template para un miembro de plantilla dependiente
        int* p = T().template ptr<U>();
        p->~U(); // U es int,  llama al pseudodestructor de int
        delete p;
    }
};
template<> int A<P>::sn = 2;
 
int main()
{
    A<P> a(1);
    std::cout << a.n << ' '
              << a.sn << ' '   // A::sn también funciona
              << a.f() << ' ' 
              << a.sf() << ' ' // A::sf() también funciona
//            << a.B << ' '    // error: no se permite tipo anidado
              << a.RED << ' '; // enumerado
}

Salida:

1 2 11 4 1


[editar] Operadores de acceso puntero a miembro integrados

Las expresiones de operador de acceso a miembro a través de punteros a miembro tienen la forma

lhs .* rhs (1)
lhs ->* rhs (2)
1) lhs debe ser una expresión de tipo clase T.
2) lhs debe ser una expresión de tipo puntero a tipo clase T*.

El segundo operando de ambos operadores es una expresión de tipo puntero a miembro ( dato o función) de T o puntero a miembro a una clase base B de T, sin ambigüedad y accesible.

La expresión E1->*E2 es exactamente equivalente a (*E1).*E2 para los tipos integrados; es por esto que las siguientes reglas se refieren solamente a E1.*E2.

En la expresión E1.*E2:

1) si E2 es un puntero a miembro dato,
  • si E1 es un lvalue, el resultado es una lvalue que designa a ese miembro de datos,
  • en otro caso (si E1 es un rvalue (hasta C++17)xvalue (que podría ser obtenido de un prvalue) (desde C++17)), el resultado es un rvalue (hasta C++11)xvalue (desde C++11) que designa ese miembro de datos;
2) si E2 es un puntero a un miembro función, el resultado es un tipo especial de prvalue que designa ese miembro función que solamente se puede usar como operando izquierdo del operador de llamada a función miembro, y no para otro propósito;
3) las reglas de calificación constante/volátil son las mismas que para el operador miembro de objeto, con una regla adicional: un puntero a miembro que se refiere a un miembro mutable no se puede usar para modificar ese miembro en un objeto constante;
4) siE2 es un puntero a miembro de valor nulo, el comportamiento es indeterminado;
5) si el tipo dinámico de E1 no contiene el miembro a que se refiere E2, el comportamiento es indeterminado;
6) si E1 es un rvalue y E2 apunta a una función miembro con el calificador de referencia &, el programa está mal formado a menos que la función miembro sea también calificada constante pero no volátil (desde C++20);
7) si E1 es un lvalue y E2 apunta a una función miembro con el calificador referencia &&, el programa está mal formado.

En la resolución de sobrecarga de operadores definidos por usuario, para cada combinación de tipos D, B, R, donde el tipo de clase B es la misma clase de D o una clase base de D sin ambigüedad y accesible, y R es un tipo objeto o función, los siguientes modelos de función participan en la resolución de sobrecarga:

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

Donde ambos operandos podrían ser calificados constante/volátil, en cuyo caso la calificación constante/volátil del tipo devuelto es la unión de las cualificaciones de los operandos.


#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; // error: no se puede modificar a través de mutable
    std::cout << s.*pmi << '\n';
 
    D d(7); // punteros de base funcionan con objetos derivados
    D* pd = &d;
    std::cout << (d.*pf)(7) << ' '
              << (pd->*pf)(8) << '\n';
}

Salida:

7
14 15

[editar] Biblioteca estándar

Operador subíndice está sobrecargado por muchas clases de contenedores estándar

acceso a un bit específico
(función miembro público de std::bitset) [editar]
proporciona acceso indexado a la matriz gestionada
(función miembro público de std::unique_ptr) [editar]
acceso al carácter especificado
(función miembro público de std::basic_string) [editar]
acceder al elemento especificado
(función miembro público de std::array) [editar]
acceder al elemento especificado
(función miembro público de std::deque) [editar]
acceder al elemento especificado
(función miembro público de std::vector) [editar]
acceder al elemento especificado
(función miembro público de std::map) [editar]
acceder al elemento especificado
(función miembro público de std::unordered_map) [editar]
acceso a un elemento por su índice
(función miembro público de std::reverse_iterator) [editar]
obtiene la referencia rvalue al elemento indexado
(función miembro público de std::move_iterator) [editar]
obtener / establecer un elemento de valarray, sector o máscara
(función miembro público de std::valarray) [editar]
devuelve sub-coincidencias especificadas
(función miembro público de std::match_results) [editar]

Los operadores indirección y miembro están sobrecargados por varios iteradores y clase de punteros inteligentes

desreferencia el puntero al objeto gestionado
(función miembro público de std::unique_ptr) [editar]
desreferencia de puntero al objeto gestionado
(función miembro público de std::shared_ptr) [editar]
accede al objeto gestionado
(función miembro público de std::auto_ptr) [editar]
dereferencia el iterador
(función miembro público de std::raw_storage_iterator) [editar]
desreferencia el iterador subyacente decrementado
(función miembro público de std::reverse_iterator) [editar]
no-op
(función miembro público de std::back_insert_iterator) [editar]
no-op
(función miembro público de std::front_insert_iterator) [editar]
no-op
(función miembro público de std::insert_iterator) [editar]
accede al elemento apuntado
(función miembro público de std::move_iterator) [editar]
devuelve el elemento actual
(función miembro público de std::istream_iterator) [editar]
no-op
(función miembro público de std::ostream_iterator) [editar]
(desde C++11)(hasta C++17)
obtiene una copia del carácter actual
accede a un miembro del carácter actual, si CharT tiene miembros
(función miembro público de std::istreambuf_iterator) [editar]
no-op
(función miembro público de std::ostreambuf_iterator) [editar]
accede a la coincidencia actual
(función miembro público de std::regex_iterator) [editar]
accede a la subcoincidencia actual
(función miembro público de std::regex_token_iterator) [editar]

Clases de biblioteca no estándar sobrecargan operator&. El caso más conocido de sobrecarga de operator& es la clase Microsoft COM CcomPtr, aunque también puede aparecer en EDSLs como boost.spirit

Clases de biblioteca no estándar sobrecargan operator->*. Se sugirió que podría ser parte de smart pointer interface, y de hecho es utilizado en esa capacidad por actores en boost.phoenix, pero es más común en EDSLs como cpp.react.

[editar] Informe de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
CWG 1213 C++11 subíndice en una matriz rvalue deriva en lvalue reclasificado como xvalue

[editar] Ver también

La precedencia de operadores

Sobrecarga de operadores

Operadores comunes
asignación incremento/decremento aritmético lógico comparación acceso a miembro otros

a = b
a = rvalue
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
? :

Operadores especiales

static_cast convierte de un tipo a otro tipo compatible
dynamic_cast convierte de clase base virtual a clase derivada
const_cast convierte de un tipo a otro compatible con diferentes calificadores constante/volátil
reinterpret_cast convierte el tipo a tipo incompatible
new asigna memoria
delete desasigna memoria
sizeof consulta el tamaño de un tipo
sizeof... consulta el tamaño de un parámetro de paquete (desde C++11)
typeid consulta la información de un tipo
noexcept comprueba si una expresión puede lanzar una excepción (desde C++11)
alignof consultas requisitos de alineación de un tipo (desde C++11)

Documentacion C de Operadores de acceso a miembro