2015-10-17 7 views
15

Stavo provando un programma di test sui guasti di apertura di un file usando ifstream. Il codice è qui sotto: -C++ L'oggetto ifstream è uguale a nullptr ma non è un puntatore?

#include <iostream> 
#include <fstream> 
#include <type_traits> 
using namespace std; 
int main() 
{ 
    ifstream ifs ("wrong_filename.txt"); 
    cout << boolalpha; 
    cout << is_pointer<decltype(ifs)>::value <<"\n"; 
    cout << (ifs==nullptr); 
    return 0; 
} 

uscita è: -

false 
true 

Se ifs non è un pointer, allora come fa pari a nullptr?

+0

C'è un sovraccarico del cast per 'void *' IIRC. –

+0

Qualsiasi tipo di classe può scegliere di essere paragonabile a un 'nullptr' definendo una conversione implicita a un tipo di puntatore o sovraccaricando' operator == 'in modo appropriato. –

+2

Assegna un nome al compilatore quando si richiede un "dubbio". –

risposta

22

Fino a C++ 11, i flussi C++ sono implicitamente convertibili in void*. Il risultato sarà NULL se lo stream non è in uno stato senza errori e qualcos'altro se lo è. Quindi ifs == NULL (non dovrebbe funzionare con nullptr, vedi sotto) troverà e userà quella conversione, e dal momento che il tuo nome file è sbagliato, il confronto produrrà vero.

In C++ 11, questo è stato cambiato per una conversione esplicita per bool, con false che indica un errore e true un buon flusso, perché la conversione void* permesso codice troppo senza senso, come il tuo esempio. In effetti, un compilatore corrente in modalità C++ 11 o C++ 14 rifiuterà il frammento di codice, live. Poiché il tuo codice è ovviamente almeno C++ 11, il tuo compilatore non è conforme accettandolo.

quelle conversioni consentono e sono destinati per i controlli di errore come questo:

if (!(ifs >> data)) 
    std::cout << "Reading data failed."; 

o, analogo a tuo esempio:

std::ifstream ifs ("wrong_filename.txt"); 
if (!ifs) 
    std::cout << "Could not open file."; 

Fun fatto del giorno: è anche possibile utilizzare questo per pulire in modo pulito su un file, ad esempio:

for (std::string line; std::getline(ifs, line);) { 
    // Process line 
} 
+0

hey! cout << (ifs == false) genera anche l'errore – CppNITR

+0

@CppNITR è necessario un * contesto booleano *, ovvero un contesto che attiva le conversioni booleane esplicite. Ad esempio, un cast per 'bool', una condizione' if' o la seconda parte di un header 'for'. – Quentin

+0

@CppNITR Perché la conversione 'bool' è' explicit'. Buona cattura, aggiornata la risposta, grazie. –

Problemi correlati