2012-09-18 15 views
6

Il codice seguente restituisce una stringa letterale in un file con entrambi i flussi anonimi e con nome:Anonymous std :: ofstream gestisce array di caratteri erroneamente

#include <fstream> 

using namespace std; 

int main() 
{ 
    ofstream("testfile") << "test" << endl; 

    ofstream ofs ("testfile2"); 
    ofs << "test2" << endl; 

    return 0; 
} 

Come si può vedere dalla uscita di strace, solo lo stream denominato funziona:

open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 
write(3, "0x400a91\n", 9)    = 9 
close(3)        = 0 
open("testfile2", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 
write(3, "test2\n", 6)     = 6 
close(3)        = 0 

Inoltre, se si utilizza std :: string anziché letterale, non riesce a compilare.

Perché è questo?

risposta

4

In C++ 03, gli operatori non membri che emettono i puntatori e le stringhe di caratteri non possono essere chiamati con un valore rvalue, poiché richiedono un riferimento lvalue, quindi viene chiamato il membro operator<<(const void *). In C++ 11 questo è risolto scrivendo sovraccarichi che prendono un riferimento di rvalue, ma in C++ 03 è possibile aggirare il problema chiamando una funzione membro o un operatore membro che restituisce un riferimento lvalue (si noti che le funzioni membro non const può essere chiamati rvalues):

ofstream("testfile").write("", 0) << "test" << endl; 

Si può facilmente scrivere un manipolatore per fare questo:

std::ios_base& (*do_nothing)(std::ios_base&)) {} 

ofstream("testfile") << do_nothing << "test" << endl; 
+0

Accettare questa risposta perché la soluzione funziona su C++ 03. Grazie! –

9

Si ha un problema che lo "stream anonimo" è un valore rvalore, e con C++ 98 è possibile solo chiamare funzioni membro su di esso. Il stream << "test" si collegherà a un membro prendendo un void* che emette l'indirizzo del puntatore.

C++ 11 ha aggiunto un operator<< che accetta un flusso di valore e che farà funzionare il codice.

+0

Oh palle, ho dimenticato la non memberness. Hai vinto. – Puppy