2015-10-17 13 views
15

Próbowałem program testowy na niepowodzenie otwierania pliku przy użyciu ifstream. Kod jest poniżej: -C++ Obiekt ifstream jest równy nullptr, ale nie jest wskaźnikiem?

#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; 
} 

wyjściowa wynosi: -

false 
true 

Jeśli ifs nie jest pointer, to w jaki sposób to robi równe nullptr?

+0

Występuje przeciążenie obsady dla 'void *' IIRC. –

+0

Dowolny typ klasy może wybrać porównywalność z 'nullptr', definiując niejawną konwersję na typ wskaźnika, lub odpowiednio przeciążając' operator == '. –

+2

Nazwij kompilator, pytając o "wątpliwości". –

Odpowiedz

22

Do czasu, gdy strumienie C++ 11, C++ są niejawnie wymienialne na void*. Rezultatem będzie NULL, jeśli strumień nie jest w stanie bezbłędnym, a jeśli nie, to jest inny. Tak więc ifs == NULL (nie powinno działać z nullptr, patrz poniżej) odnajdzie i użyje tej konwersji, a ponieważ nazwa pliku była błędna, porównanie przyniesie prawdziwe wyniki.

w C++ 11, zostało to zmienione na jawnej konwersji bool z false wskazując błąd i true dobry Stream, ponieważ konwersja void* dozwolony kod zbyt wiele bezsensowny, takie jak np. Rzeczywiście, bieżący kompilator w trybie C++ 11 lub C++ 14 odrzuci Twój kod, live. Ponieważ twój kod to oczywiście C++ 11, twój kompilator nie jest zgodny z jego akceptacją.

tych konwersji umożliwiają i są przeznaczone do kontroli błędach tak:

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

lub analogicznie do przykładu:

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

Ciekawostka dnia: Można również użyć to, aby wyczyścić pętlę nad plikiem, na przykład:

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

hej! cout << (ifs == false) również zgłasza błąd – CppNITR

+0

@CppNITR potrzebujesz * kontekstu logicznego *, który jest kontekstem, który wyzwala jawne konwersje boolowskie. Na przykład rzutowanie na 'bool', warunek' if' lub druga część nagłówka 'for'. – Quentin

+0

@CppNITR Ponieważ konwersja 'bool' jest' jawna'. Dobry połów, zaktualizowałem odpowiedź, dzięki. –

Powiązane problemy