2011-08-13 26 views
11

¿Usar el puntero "this" agrega otra operación al programa en tiempo de ejecución?¿Hay alguna diferencia entre utilizar este puntero y no usarlo?

Sólo para dar un ejemplo para explicar mejor la cuestión:

class C 
{ 
public: 
    void set_x(int val){ x = val; } 
    void set_this_x(int val){ this->x = val; } 

private: 
    int x; 
}; 

hace la función "C :: set_x()", durante el tiempo de ejecución, realiza menos 1 operación de "C :: set_this_x()" ?

Gracias! :-)

Respuesta

19

No hay diferencia entre las funciones de dos miembros. Tiene que ser, ya que esto es lo que el estándar C++ (ISO/IEC 14882: 2003) tiene que decir:

9.3.1 funciones miembro no estáticos [class.mfct.nonstatic]

2. Cuando se usa id-expression (5.1) que no es parte de un miembro de clase sintaxis de acceso (5.2.5) y no se utiliza para formar un puntero al miembro (5.3.1) en el cuerpo de una función miembro no estática de la clase X o utilizado en el mem-initializer para un constructor de la clase X, si nam e lookup (3.4.1) resuelve el nombre en el id-expression a un miembro no tipológicas no estático de la clase X o de una clase base de X, la id-expression se transforma en una expresión de acceso miembro de la clase (5.2.5) usando (*this) (9.3.2) como la expresión de postfijo a la izquierda del operador .. El nombre del miembro se refiere al miembro del objeto para el que se llama a la función.

5.2.5 acceso miembro de la Clase [expr.ref]

3. Si E1 tiene el “puntero a la clase X,” tipo entonces la expresión E1->E2 se convierte en la forma equivalente (*(E1)).E2;. ..

Por lo que significa el siguiente código:

class C 
{ 
public: 
    void set_x(int val) { x = val; } 
    void set_this_x(int val) { this->x = val; } 
private: 
    int x; 
}; 

se habría transformado en el siguiente código de acuerdo con 9.3.1/2 y 5.2.5/3:

class C 
{ 
public: 
    void set_x(int val)  { (*this).x = val; } // as per 9.3.1/2 
    void set_this_x(int val) { (*(this)).x = val; } // as per 5.2.5/3 
private: 
    int x; 
}; 

Para mostrar que no hay realmente ninguna diferencia, al menos por un compilador, he aquí una comparación lado a lado del desmontaje de la función C::set_x() y C::set_this_x() de VC++ compilador emite con optimizaciones desactivado (/Od):

void set_x(int val){ x = val; }  void set_this_x(int val){ this->x = val; } 
push  ebp      push  ebp 
mov  ebp,esp     mov  ebp,esp 
sub  esp,0CCh     sub  esp,0CCh 
push  ebx      push  ebx 
push  esi      push  esi 
push  edi      push  edi 
push  ecx      push  ecx 
lea  edi,[ebp-0CCh]    lea  edi,[ebp-0CCh] 
mov  ecx,33h     mov  ecx,33h 
mov  eax,0CCCCCCCCh    mov  eax,0CCCCCCCCh 
rep stos dword ptr es:[edi]   rep stos dword ptr es:[edi] 
pop  ecx      pop  ecx 
mov  dword ptr [ebp-8],ecx  mov  dword ptr [ebp-8],ecx 
mov  eax,dword ptr [this]  mov  eax,dword ptr [this] 
mov  ecx,dword ptr [val]  mov  ecx,dword ptr [val] 
mov  dword ptr [eax],ecx  mov  dword ptr [eax],ecx 
pop  edi      pop  edi 
pop  esi      pop  esi 
pop  ebx      pop  ebx 
mov  esp,ebp     mov  esp,ebp 
pop  ebp      pop  ebp 
ret  4       ret  4 

Nota que el compilador produce el mismo conjunto exacto para ambas funciones miembros.

9

No, no hace una diferencia de tiempo de ejecución, es solo sintaxis. Todavía se accede al puntero this en la primera función, solo se especifica implícitamente en lugar de explícitamente.

Por cierto, esto huele a una optimización prematura: primero escriba el código de limpieza, luego el código rápido.

+0

+1: código limpio primero! – Johnsyweb

+0

Gracias por su respuesta! :-) No estoy haciendo ninguna optimización aún, solo pensando en lugares que se pueden hacer cuando llegue el momento. Una vez me quemó por una optimización prematura, tuve suficiente de eso :-). – TCS

3

No, no hay diferencia.
cuando refiere a un miembro directamente, el compilador lo desclasifica a través del this.

2

Si tropezó con esa expresión en el código de otra, es probable que se originó en algo como esto:

struct A 
{ 
    int x; 

    void set_X(int x) 
    { 
     this->x = x; 
    } 
}; 
2

No hay diferencia, el compilador genera ya automáticamente el código para esto:> A pesar de que es superflua sintaxis, hay dos buenas razones para utilizarlo:

  • utilizando un editor que soporta auto-realización. Cuando escribe "this->", el editor muestra una ventana de herramientas que presenta una lista de miembros de la clase para elegir. Esto puede acelerar el tipeo y ayuda a evitar errores de compilación tontos debido a errores de tipeo.

  • ayuda a evitar tener que inventar nombres de argumentos artificiales. Puede dar al argumento el mismo nombre que el miembro de la clase: void set_x (int x) {this-> x = x; }.

3

Es lo mismo. Sin embargo, "esto" puede usarse para desambiguar en ciertos casos.

class C 
{ 
public: 
    void set_x(int x){ x = x; } // does nothing 
    void set_this_x(int x){ this->x = x; } // sets the variable 

private: 
    int x; 
}; 
1

Una de las veces que importa es cuando le da a una variable local el mismo nombre que un miembro de la clase. Por ejemplo:

class Example { 

public: 

    int something(); 
    int somethingElse(); 

} 


int Example::somethingElse() { 
    int something = something(); // ERROR 
    int something = this->something(); // OK 
    // ... 
} 
+0

Hay lugares en la programación de plantillas en los que también debe recurrir al uso de 'this'. Grep para 'this->' en la biblioteca estándar de C++ y verá que el código está salpicado con 'this->'. –

2

que se puede decir foo en lugar de this->foo es sólo azúcar sintáctico. No hay diferencia en el código compilado. Como todos los azúcares sintácticos, un pequeño puñado lo desaprueba pero la mayoría lo ama. Para ver en qué posición se encuentra al respecto, intente utilizar un lenguaje como perl o python que no proporcione este azúcar sintáctico. El código de Python está salpicado de self.foo; en el código OO de Perl verá self->foo por todas partes. Puede ser un poco molesto. Se requiere

6

La sintaxis this->member si se hereda de una plantilla de clase:

+3

Se necesita algo para superar el problema de que 'x' es un nombre no dependiente, pero ese algo no es necesariamente' this-> x'. Se podría usar 'usando Base :: x' dentro de la declaración de clase o usar' int b = Base :: x; 'en la función' Derived :: whatever'. –

+0

Este ejemplo es incorrecto porque 'Derived' no tiene una clase base dependiente. –

+0

@Johannes: ¿Mejor? Si no, arregla. – fredoverflow

Cuestiones relacionadas