2013-08-03 10 views
5

Dato il seguente frammento di codice: programmatoreC++ enigma di programmazione, divertirsi con i puntatori a funzione

#include <string> 
#include <iostream> 

int main() 
{ 
    std::string prefix("->"), middle(), suffix("<-"); 
    std::cout << "Test: " << prefix << middle << suffix << std::endl; 

    return 0; 
} 

L'avanzato C++ immediatamente vedere che middle() non sta chiamando std::string s' ctor di default, invece si tratta di una dichiarazione di funzione.

La cosa interessante però: Perché gcc produce il seguente output:

Test: ->1<- 

a differenza di errore di linker di Visual Studio? Qualcuno sa cosa sta succedendo qui?

+0

Ho un downvote e una richiesta stretta per questa domanda (off-topic), qualcuno può forse dirmi perché. Una domanda del genere è davvero fuori tema su SO? –

risposta

7

Un puntatore a funzione verrà convertito in bool quando si utilizza con cout.

Perché il puntatore di funzione non viene convertito in un void * implicitamente, qual è l'overload di operatore < <? perché i puntatori di funzione non sono puntatori di oggetti.

C++ 11 §4.10/2:

Un prvalue di tipo “puntatore a cv T”, dove T è un tipo di oggetto, può essere convertito in un prvalue di tipo “puntatore a vuoto cv ”. Il risultato della conversione di un "puntatore in cv T" in un "puntatore al cv void" punta all'inizio della posizione di memoria in cui risiede l'oggetto di tipo T, come se l'oggetto fosse un oggetto più derivato (1.8) di tipo T (cioè, non un subobject di classe base). Il valore del puntatore nullo viene convertito nel valore del puntatore nullo del tipo di destinazione.

+2

Grazie, stavo indovinando qualcosa del genere. Sai per caso perché VS produce invece un errore di linker? Quale comportamento è "standard" e quale è "sbagliato"? –

+4

@ D.R .: Penso che il tuo programma abbia un comportamento indefinito, quindi entrambi sono "corretti". Ecco la regola: "Ogni programma deve contenere esattamente una definizione di ogni funzione o variabile non incorporata odr-utilizzata in quel programma; ** nessuna diagnostica richiesta **." –

+0

Che dire di questo? http://stackoverflow.com/questions/2064692/how-to-print-function-pointers-with-cout –

1

Come detto da Yu, il puntatore della funzione viene convertito in bool.

L'ottimizzatore g ++ sta evidentemente pre-valutando la conversione, mentre Visual C++ genera effettivamente il codice per verificare se l'indirizzo della funzione è nullo, il che richiede che il linker fornisca l'indirizzo della funzione.

La regola è che

Ogni programma deve contenere esattamente un definizione di ogni funzione non inline o variabile che viene ODR-usata in quel programma; nessuna diagnostica richiesta.

La funzione è ODR-utilizzato perché si sta usando il suo indirizzo. Non fornendo una definizione, stai violando questa regola e lo Standard non richiede una diagnostica, il che significa che la toolchain è libera di fare tutto ciò che vuole.

Visual C++ sta generando una diagnostica, anche se non è necessario.

g ++ sta dando il risultato effettivo della conversione a bool, poiché sa che il decadimento di una funzione effettiva su un puntatore di funzione non può mai produrre un puntatore a funzione nulla.

Ma la formattazione del disco rigido sarebbe ugualmente valida, dal momento che lo standard non dice quello che la toolchain può o non può fare qui.