2015-11-04 10 views
5

So che quando si utilizza il nome di una funzione come valore, la funzione viene automaticamente convertita in un puntatore. un'occhiata al seguente codice:assegnazione del puntatore a funzione e chiamata in C++?

int print(int a) 
{ 
    return a; 
} 

int main() 
{ 
    int (*p)(int) = print; 
    int (*q)(int) = &print; 

    cout << p(8) << endl; 
    cout << (*p)(8) << endl; 
} 

perché sono int (*p)(int) = print;, stampa è un puntatore, e int (*p)(int) = &print;, & stampa è un indirizzo a un puntatore, equivalente?

D'altra parte, quando si utilizza un puntatore a una funzione per chiamare la funzione, perché sono p(8) e (*p)(8) equivalenti?

+0

Credo che è solo per convenienza , che non è necessario deferire esplicitamente i puntatori alle funzioni quando li si utilizza per chiamare la funzione. Se usi 'typedefs' puoi lavorare con il puntatore a funzione senza usare' * 'quale imho è abbastanza bello – user463035818

+2

Possibile duplicato di [Come si verifica il dereferenziamento di un puntatore a funzione?] (Http://stackoverflow.com/questions/2795575/how-fa-dereferencing-of-a-function-pointer-happen) –

+0

@SimonKraemer grazie. Ma il collegamento spiega solo il dereferenziamento, la mia domanda include anche l'assegnazione del puntatore a funzione. – sydridgm

risposta

2

print è una funzione, ma è implicitamente convertibile in un tipo di puntatore a funzione. Citato da cppref:

funzione di puntatore
un lvalue di tipo funzione T può essere implicitamente convertito in un puntatore prvalue a tale funzione. Ciò non si applica a funzioni membro non statiche poiché non sono presenti i valori lvalue che fanno riferimento alle funzioni membro non statiche .

Quindi, nel tuo caso:

int (*p)(int) = print; // Conversion happens. 
int (*q)(int) = &print; // Conversion does not happen. 

calci di conversione implicita in automaticamente quando è necessario per rendere la compilazione del programma, e non si applica in caso contrario.

Rispetto alla chiamata di funzione, si tratta della funzione di chiamata di funzione integrata (). Secondo cppref, l'operatore di chiamata di funzione built-in è applicabile sia a un'espressione lvalue che fa riferimento a una funzione che a un puntatore alla funzione. Nel tuo caso:

p(8); // The function call operator is applied to a pointer to function. 
(*p)(8); // The function call operator is applied to an lvalue reference to function. 

Per riferimento (enfasi mia):

chiamata di funzione incorporata espressione operatore
Una chiamata di funzione, come E (A1, A2, A3) , consiste in un'espressione che denomina la funzione, E, seguita da un possibile elenco vuoto di di espressioni A1, A2, A3, ..., tra parentesi.L'espressione che i nomi della funzione può essere

a) lvalue che fa riferimento a una funzione
b) puntatore a funzione
...

3

print è non un puntatore. Il suo tipo è int(int), non int(*)(int). Questa distinzione è particolarmente importante nel tipo di deduzione

auto& f = print; //type of f is int(&)(int), not int(*(&))(int) 
template<typename Func> 
foo(Func& f); 
foo(print); //Func is deduced to be int(int), not int(*)(int) 

Analogamente agli array, non è possibile copiare una funzione "per valore", ma è possibile passare in giro il suo indirizzo. Ad esempio,

int arr[4];  //the type of arr is int[4], not int* 
int *a = arr; //automatic array-to-pointer decay 
int (*a)[4] = &arr; //type match 
int (*p)(int) = print; //automatic function-to-pointer decay 
int (*p)(int) = &print; //type match 

Ora, quando si chiamano print attraverso p,

p(8)  //automatic dereferencing of p 
(*p)(8) //manual dereferencing of p 
+0

la tua risposta ha un senso. ma nel libro ** C++ primer 5th edition ** e molti altri tutorial sul sito Web hanno detto che usare il nome della funzione come valore rvalue lo convertirà in un puntatore. Quindi non so se la tua risposta è una condizione speciale per l'assegnazione del puntatore alla funzione. – sydridgm

+0

@sydridgm Sono corretti. E si riferiscono al decadimento da funzione a puntatore nella mia risposta. – downhillFromHere