2010-04-01 15 views
6

Vi este fragmento de código durante nuestro laboratorio y en realidad se compila en MSVC2008 y G ++.una función de clase con la prueba if (this == NULL) compilada?

void LinkList< class T >::Insert(T n) 
{ 
    if (this == NULL) 
    // some code here 
} 

Por lo que yo sé la this no debe ser nulo ya que no puede llamar a funciones de clase en C++ si no se crea una instancia. ¿Es este un código válido? en caso afirmativo, ¿cuál es el motivo y dónde puede ser útil?

+1

IT'S A TRAP !!!! – Ben

Respuesta

8

ya que no puede llamar a funciones de clase en C++ si no se crea una instancia

La cosa es, usted puede , pero leads to undefined behavior.

Dicha comprobación probablemente sea una afirmación, aunque no está garantizado que el código realmente funcione con la norma. (Si this es nulo, ya estás en la tierra un comportamiento indefinido.)


La razón por la que es "útil" es detectar el uso de un objeto después de que se ha eliminado o si nunca se creó:

template <typename T> // I hate this function 
void safe_delete(T*& pPtr) 
{ 
    delete pPtr; 
    pPtr = 0; 
} 

T* p = new T; 
safe_delete(p); 

p->foo(); // this is null, and we've entered undefined behavior 

Dentro de foo, puede afirmar: "hey, hemos cometido un error: /".

En mi opinión, tal uso es indicativo de un mal diseño. No debe tener un puntero que pueda ser invocado de nuevo. Lo último que hace con un puntero es delete; si todavía está disponible después de eso, cambie su código para que no lo esté.

0

si la variable de clase no está instanciada ... Su comportamiento es indefinido ... Así que el compilador no le dará error ... Pero el comportamiento de la función no está definido ... Puede funcionar incluso perfectamente bien si antes if (this == NULL) declaración no se usa ningún miembro de la clase ...

0

Dado que this es solo un puntero, el código es válido, esto significa que la comparación es válida. Si el código en el bloque condicional se ejecuta o no es otro problema.

5

Este es el tipo de problema que está tratando de 'resolver':

class A 
{ 
public: 
    void test() 
    { 
     if(this == NULL) 
     { 
      std::cout<<"This is NULL\n"; 
     } 
    } 
}; 

int main() { 
    A* p = NULL; 
    p->test(); 
    return 0; 
} 

Sin embargo, tenga en cuenta que llamar p->test() invoca un comportamiento indefinido, por lo this puede o no puede ser nulo. Supongo que alguien estaba muy apurado y eligió hacerlo en lugar de resolver el problema real. No lo use, nunca funcionará de manera confiable o predecible. En cuanto a por qué se compila, this es solo un puntero de const y la comparación de un puntero a NULL es sintácticamente válida.

0

Según el estándar C++, es un comportamiento indefinido. Sin embargo, un C implementación típica ++ tratará a una función miembro no virtual

void A::func(int arg); 

como la función de estilo C

void A_func(A* this, int arg); 

Y al igual que cualquier argumento de un puntero, que está bien que "este" ser NULL siempre y cuando no desreferencia la memoria.Por lo tanto, si escribe:

#include <iostream> 

class A 
{ 
    public: 
     void test(); 
}; 

void A::test() 
{ 
    std::cout << "This function could have been static." << std::endl; 
} 

int main() 
{ 
    ((A*) NULL)->test(); 
    return 0; 
} 

Correrá bien (al menos en MSVC y G ++).

Sin embargo, esto da un fallo de segmentación:

#include <iostream> 

class A 
{ 
    public: 
     void test(); 

    private: 
     int _n; 
}; 

void A::test() 
{ 
    _n = 42; 
} 

int main() 
{ 
    ((A*) NULL)->test(); 
    return 0; 
} 

El caso (esto == NULL) cheque es un intento de evitar una referencia a un puntero nulo se estrelle el programa.

Pero para cumplir con la norma, es mejor hacer la prueba desde el exterior.

if (pList != NULL) 
{ 
    pList->Insert(value); 
} 
Cuestiones relacionadas