2009-09-13 20 views

Respuesta

14

Para ambos punteros de función y objeto, que compilan pero su resultado no está garantizado para ser consistente para las direcciones a la sub- objetos del mismo objeto completo (puede comparar las direcciones de dos miembros de una clase o matriz) y si compara una función u objeto contra sí mismo.

Usando std::less<>, std::greater<> y así sucesivamente funcionará con cualquier tipo de puntero, y dará resultados consistentes, incluso si el resultado del respectivo operador incorporado es no especificado:

void f() { } 
void g() { } 

int main() { 
    int a, b; 

    ///// not guaranteed to pass 
    assert((&a < &b) == (&a < &b)); 

    ///// guaranteed to pass 
    std::less<int*> lss1; 
    assert(lss1(&a, &b) == lss1(&a, &b)); 
    // note: we don't know whether lss1(&a, &b) is true or false. 
    //  But it's either always true or always false. 

    ////// guaranteed to pass 
    int c[2]; 
    assert((&c[0] < &c[1]) == (&c[0] < &c[1])); 
    // in addition, the smaller index compares less: 
    assert(&c[0] < &c[1]); 

    ///// not guaranteed to pass 
    assert((&f < &g) == (&f < &g)); 

    ///// guaranteed to pass 
    assert((&g < &g) == (&g < &g)); 
    // in addition, a function compares not less against itself. 
    assert(!(&g < &g)); 

    ///// guaranteed to pass 
    std::less<void(*)()> lss2; 
    assert(lss2(&f, &g) == lss2(&f, &g)); 
    // note: same, we don't know whether lss2(&f, &g) is true or false. 

    ///// guaranteed to pass 
    struct test { 
    int a; 
    // no "access:" thing may be between these! 
    int b; 

    int c[1]; 
    // likewise here 
    int d[1]; 

    test() { 
     assert((&a < &b) == (&a < &b)); 
     assert((&c[0] < &d[0]) == (&c[0] < &d[0])); 

     // in addition, the previous member compares less: 
     assert((&a < &b) && (&c[0] < &d[0])); 
    } 
    } t; 
} 

Todo eso debería compilar sin embargo (aunque el compilador puede advertir sobre cualquier fragmento de código que quiera).


Dado que los tipos de función no tienen ningún sizeof valor, las operaciones que se definen en términos de sizeof del tipo pointee no va a funcionar, estos incluyen:

void(*p)() = ...; 
// all won't work, since `sizeof (void())` won't work. 
// GCC has an extension that treats it as 1 byte, though. 
p++; p--; p + n; p - n; 

Los unarios + funciona en cualquier tipo de puntero, y simplemente devolverá el valor de la misma, no hay nada especial para los indicadores de función.

+ p; // works. the result is the address stored in p. 

Finalmente nota de que un puntero a una función puntero no es un puntero de función más:

void (**pp)() = &p; 
// all do work, because `sizeof (void(*)())` is defined. 
pp++; pp--; pp + n; pp - n; 
+0

¿Tiene alguna referencia que enumere todas las operaciones soportadas por punteros de función como ++, + n, - n, -, + – yesraaj

+1

gran explicación como siempre :-), Gracias Litb – yesraaj

+0

Gracias, me alegro de que te ayude :) –

1

# 1: Se pueden invocar los punteros a las funciones.

# 2: Los operadores relacionales son compatibles con punteros porque puede usarlos en aritmética de punteros y comparar direcciones entre sí. Ejemplo práctico: Recorrido de una matriz

int data[5] = { 1, 2, 3, 4, 5 }; 

// Increment pointer until it reaches the end-address. 
for (int* i = data; i < data + 5; ++i) { 
    std::cout << *i << endl; 
} 
2

Puede comparar los punteros si apuntan a la misma asignación. Por ejemplo, si tiene dos punteros apuntando a elementos de la misma matriz, puede usar operadores de comparación de desigualdad en esos punteros. Por otro lado, si tiene dos punteros apuntando a objetos diferentes, entonces la comparación es "indefinida", sin embargo, en la práctica, la mayoría de los compiladores probablemente solo compararán las direcciones.

char *text[] = "hello"; 
const char *e_ptr = strchr(text, 'e'); 
const char *o_ptr = strchr(text, 'o'); 
if (e_ptr < o_ptr) { ... } // this is legal 
char *other_text[] = "goodbye"; 
const char *b_ptr = strchr(other_text, 'b'); 
if (b_ptr > o_ptr) { ... } // not strictly legal 
+0

Y en C++, std :: less se puede usar para comparar punteros del mismo tipo, ya sea que estén en la misma asignación o no. –

1

Los operadores <,>, < =,> = cuentan con el apoyo para los punteros, pero sólo están garantizados para producir resultados fiables si los dos punteros que se comparan son parte de la misma asignación de memoria (como comparar dos punteros a índices en una asignación de matriz). Para estos, indica posición relativa en la asignación (es decir, si es < b, entonces a apunta a un índice más bajo en la matriz que b). Para los punteros que no están en la misma asignación, el resultado es la implementación definida (y en algunas arquitecturas, puede violar estrictamente menos que la compatibilidad necesaria para los mapas. Por ejemplo, un puntero de 64 bits podría ser comparado para < o> utilizando solo el menor 32 bits, si una sola asignación no puede exceder el tamaño permitido para un puntero de 32 bits). En realidad, no tienen sentido en el contexto de los punteros de función, ya que no abordan una asignación de memoria continua.

Otras operaciones de puntero sin formato: == devuelve verdadero si los punteros apuntan al mismo objeto. - produce el número de bytes entre los dos punteros (¿me parece bien solo para la misma asignación?). + no compila, ya que no tendría sentido.

Para los punteros de función, se pueden desreferenciar * y llamar.

Para-puntero-a-miembro de funciones, están los operadores -.> * Y *

0

Un puntero se representa como un valor normal entero. Puede hacer todo con punteros, lo que también está permitido en todos los demás tipos numéricos. + - */< < >> ==! =^& | ! ~%. Espero no haber olvidado nada

Un puntero de función solo es diferente de esa manera que se puede invocar con el operador().

Cuestiones relacionadas