2012-05-20 9 views
28

Entiendo la sobrecarga normal del operador. El compilador puede traducirlos a la llamada al método directamente. No tengo muy claro el operador ->. Estaba escribiendo mi primer iterador personalizado y sentí la necesidad de -> operador. Tomé un vistazo al código fuente AWL e implementé mi propia semejante:¿Cómo funciona la sobrecarga de flecha-> operador internamente en C++?

MyClass* MyClassIterator::operator->() const 
{ 
    //m_iterator is a map<int, MyClass>::iterator in my code. 
    return &(m_iterator->second); 
} 

Entonces puede utilizar una instancia de MyClassIterator como:

myClassIterator->APublicMethodInMyClass(). 

Parece que el compilador hace dos pasos de aquí. 1. Llame al método ->() para obtener una variable temporal MyClass *. 2. Llame al APublicMethodInMyClass en la variable de temperatura y use su operador ->.

¿Es correcto mi entendimiento?

Respuesta

23
myClassIterator->APublicMethodInMyClass() 

es nada más que lo siguiente:

myClassIterator.operator->()->APublicMethodInMyClass() 

La primera llamada a la operator-> sobrecargado se obtiene un puntero de algún tipo que tiene una función miembro accesibles (desde su llamada in situ) llamada APublicMethodInMyClass(). Las reglas habituales de búsqueda de funciones se siguen para resolver APublicMethodInMyClass(), por supuesto, dependiendo de si es virtual o no.

No es necesariamente una variable temporal; el compilador puede o no copiar el puntero devuelto por &(m_iterator->second). Con toda probabilidad, esto será optimizado de distancia. Sin embargo, no se crearán objetos temporales de tipo MyClass.

Las advertencias habituales también se aplican a m_iterator - asegúrese de que sus llamadas no accedan a un iterador invalidado (es decir, si está usando vector por ejemplo).

+2

en realidad es 'myClassIterator.operator ->() -> APublicMethodInMyClass()' –

+0

Gracias por la explicación. ¿Debería el myClassIterator.operator ->(). APublicMethodInMyClass() ser myClassIterator.operator ->() -> APublicMethodInMyClass()? El tipo de devolución de ->() es MyClass * – Ryan

+0

. Gracias Seth. – Ryan

66

El operator-> tiene una semántica especial en el idioma en el que, cuando se sobrecarga, se vuelve a aplicar al resultado. Mientras que el resto de los operadores se aplican una sola vez, el compilador aplicará operator-> tantas veces como sea necesario para llegar a un puntero sin formato y una vez más para acceder a la memoria referida por ese puntero.

struct A { void foo(); }; 
struct B { A* operator->(); }; 
struct C { B operator->(); }; 
struct D { C operator->(); }; 
int main() { 
    D d; 
    d->foo(); 
} 

En el ejemplo anterior, en la expresión d->foo() el compilador tomará el objeto d y aplicar operator-> a ella, lo que produce un objeto de tipo C, se vuelva a aplicar el operador para obtener una instancia de B, vuelva a aplicar y llegue a A*, después de lo cual desreferenciará el objeto y obtendrá los datos apuntados.

d->foo(); 
// expands to: 
// (*d.operator->().operator->().operator->()).foo(); 
// D   C   B   A* 
+1

¿Puede indicarme una referencia al respecto? Parece que no puede encontrar ninguno. Nadie más lo menciona. –

+7

@MilindR: 13.5.6/1 [...] * Una expresión x-> m se interpreta como '(x.operator ->()) -> m' para un objeto de clase x de tipo T si' T: : operator ->() 'existe y si el operador es seleccionado como la mejor función de coincidencia por el mecanismo de resolución de sobrecarga * Si' x-> operator ->() 'produce un puntero, se desreferencia, si produce un objeto de un tipo que sobrecarga 'operator ->()' que llama al operador. –

+2

Esta debería ser la respuesta correcta. –