2009-05-29 10 views
16

Sono un principiante in C++, mi dispiace se la domanda è troppo semplice.C++ empty Costruttore di stringhe

Ho cercato di raccogliere i costrutti di stringa e provarli tutti (per ricordarli).

string strA();   // string(); empty string // incorrect 
string strB("Hello"); // string(const char* str) 
string strC("Hello",3); // string(const char* str, size_type length) 
string strD(2,'c');  // string(size_type lenght, const char &c) 
string strE(strB);  // string(const string& s) 

cout << strA << endl; 
cout << strB << endl; 
cout << strC << endl; 
cout << strD << endl; 
cout << strE << endl; 

Tutti loro lavori, ad eccezione del strA. Stampa "1". Perché? In questo caso, qual è il tipo di strA? Come posso verificare il tipo di cose quando non sono sicuro?

ho notato che il modo corretto è questo (che tra l'altro sembra essere in contrasto con gli altri costruttori, talvolta parens volte senza parentesi):

string strA; 

ps: domanda in grassetto solito irrilevante le risposte saranno downvoted.

risposta

32

Questo è un trucco molto popolare. La grammatica del C++ è ambigua. Una delle regole per risolvere le ambiguità è "se qualcosa sembra dichiarazione è una dichiarazione". In questo caso invece di definire una variabile hai dichiarato un prototipo di funzione.

string strA(); 

è equivalente a

string strA(void); 

un prototipo di una funzione no-arg che restituisce stringa.

Se si desidera chiamare esplicitamente costruttore no-arg provare questo:

string strA=string(); 

Non è del tutto equivalente - che significa 'creare una stringa temporanea utilizzando costruttore no-arg e poi copiarlo per inizializzare variabili strA ', ma al compilatore è permesso di ottimizzarlo e omettere la copia.

EDIT: Here is an appropriate item in C++ FAQ Lite

+3

E questo è uno dei motivi per cui ho smesso di usare C++. –

+3

@Dietrich Epp: anche questo mi ha infastidito. Immagino che questo sia il prezzo pagato per mantenere la compatibilità con C. L'alternativa essendo l'uso di C, che ha i suoi problemi metrici, la mia ipotesi è che sia meglio mantenere il C++ ed evitare quella trappola. – paercebal

+0

come su 'std :: string Stra ("");' – CaptainDaVinci

13

Si ritiene

string strA(); 

come una dichiarazione di funzione.

Per uso costruttore di default:

string strA; 
+2

È possibile utilizzare la notazione che nella ripartizione fuori dal mucchio: stringa * strA = new String(); – Skilldrick

6

In C++, come in C, c'è una regola che dice che tutto ciò che si presenta come un declarartion sarà trattato come una dichiarazione.

string strA(); 

si presenta come una dichiarazione di funzione, quindi è considerato come uno. Hai bisogno di:

string strA; 
1

compilatore interpreta string strA() come un prototipo di funzione di una funzione che prende argomenti vuoti e restituisce un oggetto di tipo stringa. Se si desidera creare un oggetto stringa vuoto utilizzare string strA; (senza parabrezza)

3

Esso stampa 1 perché puntatori a funzioni sono sempre convertiti in numerico come true.

+5

Solo se il puntatore a funzione è non nullo. Ad ogni modo, un puntatore alla funzione dovrebbe puntare alla sua definizione, e qui manca. Questo non dovrebbe essere collegato. – MSalters

2

tkopec è proprio su questo che non funziona. Per rispondere alla tua seconda domanda, ecco come si controlla il tipo:

template<typename TEST> void Error_() { 
    TEST* MakeError = 1; 
} 

Chiamando Error_(StrA); si otterrà un errore di compilazione, e il compilatore probabilmente vi dirà che è successo in Error_< std::basic_string<char, std::allocator<char> > (*)(void)>(std::basic_string<char, std::allocator<char> > (*)(void)) Ora, std :: basic_string> è solo std :: string, quindi questo significa davvero Error_< std::string (*)(void)> (std::string (*)(void)). La parte tra '<>' viene ripetuto tra '()', e questo è lo Sype di Stra. In questo caso, std::string (*)(void).

+0

Il tipo di strA è una funzione. std :: string (void). Non è un puntatore a funzione. Dovrebbe dichiararlo come stringa (* strA)(); se voleva che fosse un puntatore a funzione.Probabilmente so cosa intendevi, ma le tue ultime frasi suonano come se tu dicessi che è un puntatore a funzione. –

4

Non credo che in questo caso, la regola "se potesse essere una dichiarazione, è considerato una dichiarazione di" si applica. Poiché nel seguito, entrambi cose sono dichiarazioni

string a; 
string a(); 

Una è la dichiarazione di un oggetto, e l'altro è la dichiarazione di una funzione. La regola si applica in altri casi. Ad esempio, in questo caso:

string a(string()); 

In tal caso, string() può significare due cose.

  • dichiarazione di un parametro di funzione senza nome
  • Espressione la creazione di un default costruito string

Il Fule si applica qui, e string() è preso per indicare la stessa come il seguente, il parametro di nome (i nomi sono irrilevanti in parametri quando dichiara una funzione)

string a(string im_not_relevant()); 

Se una funzione prende come parametro un array o anot la sua funzione, quel parametro decade in un puntatore. Nel caso di un parametro di funzione, a un puntatore alla funzione. Così, è equivalente a quanto segue, che può sembrare più familiare

string a(string (*im_not_relevant)()); 

Ma nel tuo caso, è piuttosto la sintassi che sta facendo nella via. Sta dicendo che quanto segue è una dichiarazione di funzione. Non può mai essere la dichiarazione di un oggetto (anche se questo era probabilmente destinato dal programmatore!)

string a(); 

Quindi non c'è ambiguità in questo contesto, in primo luogo, e quindi dichiara una funzione. Dal momento che string ha un costruttore definito dall'utente, si può semplicemente omettere le parentesi, e l'effetto rimane lo stesso di quello che è stato previsto.