2012-04-11 15 views
5

Ho un paio di domande che penso sarà molto facile per qualcuno con esperienza C++ per rispondere, io grassetto le quesitons per la TL; DRstringhe C-Style per std :: string conversione chiarimento

Dato il seguente codice:

void stringTest(const std::string &s) 
{ 
    std::cout << s << std::endl; 
} 

int main() 
{ 
    stringTest("HelloWorld"); 
} 

hopefuly qualcuno può segnalare l'errore nel mio processo di pensiero qui:

Perché il parametro stringTest devono essere contrassegnate const quando passata una stringa C-Style? Non c'è una conversione implicita in una stringa std :: che si verifica utilizzando il suo costruttore di stringhe cstyle, pertanto "s" non è più un riferimento a un valore letterale (e non è necessario che sia const).

Inoltre, quale sarebbe un costruttore sguardo stringa cstyle come, e in che modo il compilatore sa invocare questo dopo aver visto:

stringTest("HelloWorld"); 

Ha semplicemente riconoscere una stringa letterale di essere qualcosa di simile a un char * ?

Mi sono imbattuto in queste domande mentre studiavo i costruttori di copie. Un altro quesiton rapida per il mio chiarimento ...

Nel caso di qualcosa come:

std::string s = "HelloWorld"; 

è il costruttore della stringa cstyle utilizzato per creare un'istanza di uno std :: string temporanea, e poi la stringa temporanea è copiato in "s" usando il costruttore di string copy?:

std::string(const std::string&); 
+0

"Perché il parametro in stringTest deve essere contrassegnato const" - indipendentemente da quando è _necessario_, si desidera rendere _all_ riferimenti 'const' che non sono effettivamente modificati. – leftaroundabout

+0

@leftaroundabout: Punto giusto, prenderò certamente questo a cuore. – Riken

+0

possibile duplicato di [Come mai un riferimento non const non può associare a un oggetto temporaneo?] (Http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to -a-temporary-object) –

risposta

2

Perché il parametro stringTest devono essere contrassegnate const quando passa una stringa C-Style?

Ha solo quando il parametro è un riferimento, dal momento che una temporanea std::string è costruito dalla char const* si passa e non const riferimento a una temporanea è illegale.

Riconosce semplicemente una stringa letterale per essere qualcosa come un char *?

Una stringa letterale è una matrice char const, che decade a char const*. Da ciò, il compilatore deduce che dovrebbe utilizzare il costruttore non explicitstd::string::string(char const *) per costruire il temporaneo.

Il costruttore cstyle utilizzato per creare un'istanza di una stringa temporanea std :: string e quindi la stringa temporanea viene copiata in "s" utilizzando il costruttore stringa copy?

È un po 'più complicato di così. Sì, viene creato un temporaneo. Ma il costruttore di copie può o non può essere chiamato; il compilatore può saltare la costruzione della copia come ottimizzazione.Il costruttore di copia deve essere ancora disponibile, però, quindi il seguente non viene compilato:

class String { 
    String(char const *) {} 
    private: 
    String(String const &); 
}; 

int main() 
{ 
    String s = ""; 
} 

Inoltre C++ 11 costruttore mossa verrà utilizzato, se disponibile; in tal caso, il costruttore di copie non è richiesto.

+0

+1 ma si potrebbe (dovrebbe) chiarire che nel terzo caso, anche se il costruttore di copie è * obbligatorio *, non viene effettivamente richiamato perché sarà (sempre - indipendentemente dall'ottimizzazione?) essere eliso . Questo è piuttosto importante anche se è "solo" un'ottimizzazione consentita. –

+0

Un letterale stringa non ha 'char const *', è 'char const [N]', che è ovviamente implicitamente convertibile in 'char const *' –

+0

@KonradRudolph: fatto ciò e ampliato un po 'sulla copia/spostamento cosa costruttore –

0

Il const string & s è in questo esempio necessario per richiamare il costruttore dall'argomento "HelloWorld". Il costruttore utilizzato è la costruzione di conversione del tipo.

A string& s non funziona perché s fa riferimento direttamente a un oggetto stringa.

La conversione del tipo è definito da qualcosa di simile a

basic_string(const _CharT* __s); 

Con un typedef

typedef basic_string<char> string; 

Quindi la dichiarazione sarebbe valutato come

basic_string(const char * __s)  
+0

Questo * sembra * sbagliato. O sei in errore o la spiegazione non è chiara. In ogni caso, 'const' non * è * richiesto per invocare un costruttore di copie. –

+0

@KonradRudolph Sembrava sbagliato perché era sbagliato, il mio cappuccio pensante era in arretrato. –

2

Perché il parametro stringTest deve essere contrassegnato come const quando passato una stringa in stile C?

MODIFICA: I documenti temporanei devono essere immutabili. Vedi commenti e risposte di Larsmans, ha ragione.

ragione semplice:

void change(std::string& c) { c = "abc"; } 
change("test"); // what should the code exactly do?? 

Inoltre, cosa sarebbe un costruttore sguardo stringa cstyle come, e in che modo il compilatore sa invocare questo dopo aver visto:

Sembra fino std::string per string(char*) costruttore

In caso di qualcosa ing come:

std::string s = "HelloWorld"; 

è il costruttore cstyle utilizzato per creare un'istanza di uno std :: string temporanea, e quindi la stringa temporanea viene copiato in "s" con il costruttore di copia stringa ?: std :: string (std const :: string &);

No. In questo caso esatto (TYPE variable = SOMETHING), è lo stesso che scrivere TYPE variable(SOMETHING);. Quindi, non viene utilizzata alcuna copia.

+0

Il tuo primo e il terzo punto sono errati. –

+0

@Konrad, sei sicuro che il terzo punto sia sbagliato? – nothrow

+0

Sì ... vedere la risposta di Larsmans (ma anche il mio commento sotto). –

2

Riconosce semplicemente una stringa letterale per essere qualcosa come un char * *?

Questa parte della domanda originale non ha avuto una risposta chiara come avrei voluto. Approvo pienamente (e ho anche votato) la risposta di Yossarian per il resto.

Fondamentalmente, è necessario capire cosa sta facendo il compilatore quando vede una stringa letterale nel codice.Quella matrice di caratteri (come qualsiasi altra stringa in stile c in realtà è) viene effettivamente memorizzata in una posizione completamente diversa rispetto al codice di cui fa parte (a seconda dell'architettura, i valori letterali numerici possono essere memorizzati nella posizione stessa come parte dell'assembly/istruzione binaria). I due blocchi di codice qui ci sono "più o meno" equivalente (ignora la mancanza di comprende o dichiarazioni di namespace):

int main(void) 
{ 
    cout << "Hello!" << endl; 
    return 0; 
} 

Questo è più vicino a ciò che è "realmente" accadendo:

const char HELLO_STR[] = { 'H', 'e', 'l', 'l', 'o', '!', 0 }; 

int main(void) 
{ 
    cout << HELLO_STR << endl; 
    return 0; 
} 

Perdonami se Ho fatto un errore in array init o qualsiasi altra cosa, ma penso che questo esprima cosa intendo per quanto riguarda la stringa letterale "veramente" memorizzata. Non è in linea, ma è una costante invisibile a un'altra parte del programma in cui è definita. Inoltre, alcuni (più?) Compilatori là fuori sistemano anche i letterali stringa "insieme" in modo che se si abbia lo stesso letterale usato in 50 posti, ne memorizza solo uno, e tutti fanno riferimento alla stessa costante, risparmiando memoria

Quindi ricorda che ogni volta che usi una stringa letterale, stai usando un const char [N] che esiste "invisibilmente" da qualche parte, che è implicitamente convertito in const char *.

Problemi correlati