2013-07-01 12 views
11

Desidero accedere all'indirizzo iniziale dell'array che viene gestito dalla classe string.Cosa restituisce il metodo c_str() dalla classe stringa?

string str="hey"; 
char* pointer=(char*)str.c_str(); 
  1. è il puntatore indicando l'indirizzo della matrice (mantenuta dalla classe string)? o la classe stringa creerà una nuova matrice dalla memoria dinamica e copierà la stringa esistente in essa e restituirà il suo indirizzo?

  2. Se questo non è il modo giusto, quindi come accedere all'indirizzo iniziale dell'array che viene gestito dalla classe stringa?

+9

* Perché * vuoi questo indirizzo? Cosa stai cercando di fare per la stringa? – trojanfoe

+1

Stai cercando una risposta C++ 11 o una C++ 03? La risposta corretta dipende da questo. Senza ulteriori specifiche, assumerei ulteriormente C++ 11. –

+0

Forse potresti rispondere alle domande in modo che possiamo rispondere meglio alla tua domanda? Sei stato qui pochi minuti fa. –

risposta

23

In C++ 11 norma è esplicitamente stabilito che .c_str() (così come nuova .data()) tornerà puntatore al buffer interno che viene utilizzato da std::string.

Qualsiasi modifica del std :: string dopo aver ottenuto il puntatore tramite .c_str()può risultato in detto char * restituito per diventare valido (ovvero - se std::string avuto internamente per riallocare lo spazio).

Nei precedenti standard C++, l'implementazione può restituire qualsiasi cosa. Ma come standard non richiedono all'utente di deallocare il risultato, non ho mai visto alcuna implementazione che restituisca qualcosa di nuovo allocato. Almeno la stringa STL di GNU gcc e MSVC++ sono array di caratura con terminazione a zero interna, che vengono restituiti da c_str().

Quindi è sicuro assumere (con normale attenzione per C++) che in qualsiasi versione di C++ in qualsiasi sua implementazione .c_str() restituirà il buffer interno.

In altre parole - si dovrebbe mai e poi mai mantenere il valore della .c_str() se non si è sicuri al 100% che è non cambierà la sua dimensione in qualsiasi momento in futuro (a meno che non si tratta di un const, che è).

P.S. A proposito, non dovresti mai fare mai char* pointer=(char*)str.c_str();. È const char * e non devi modificare il contenuto, in parte perché sopra - potresti finire per sovrascrivere la memoria di qualche altro oggetto o corrompendo lo stato interno di std::string, nel caso in cui l'implementazione faccia qualcosa di strano, come l'indicizzazione dei caratteri più veloce .find() (più recente visto questo, ma hey - questo è un incapsulamento!)

+0

Questa è esattamente la risposta che mi aspettavo. –

+0

... e, naturalmente, la modifica di una * stringa costante * avrà quasi certamente circostanze disastrose dovute a dove vive nel processo (cioè probabilmente su una pagina di memoria di sola lettura). – trojanfoe

+1

@Andrian Nord E se ci sono 0 probabilità di ridimensionamento allora ?? Ho creato un nuovo oggetto stringa e utilizzato il metodo di ridimensionamento (512). 512 è la lunghezza massima di stringa possibile nella mia applicazione. Ora se uso c_str() per ottenere l'indirizzo e poi uso il metodo append() sull'oggetto, andrà bene? –

1

È possibile ottenere l'indirizzo dell'inizio della stringa tramite char *address = &str[0];. Non c'è bisogno di convertire la stringa in rappresentazione c-string.

+2

'const char', sicuramente? –

+0

Non penso che sia garantito che funzioni correttamente. – davmac

+0

@PeterWood No, non è richiesto. –

0

In C++ 11, il puntatore ha restituito i punti all'array interno attualmente utilizzato dall'oggetto stringa per memorizzare i caratteri che ne conformano il valore.

Vedere http://www.cplusplus.com/reference/string/string/c_str/ per ulteriori dettagli.

+0

@trojanfoe il link che ho postato nella risposta dice: "Sia string :: data che string :: c_str sono sinonimi e restituiscono lo stesso valore.", Vuoi dire che è sbagliato? –

+0

@trojanfoe Le cose potrebbero essere diverse in C++ 11. Almeno http://stackoverflow.com/a/7554172/533480 ha detto così. –

+0

concordato; cancellando i miei commnets. – trojanfoe

4

NOTA: La mia risposta è corretta solo per pre-C++11. Per C++ 11, this è la risposta corretta.


  1. restituisce un C-stringa con terminazione null. std::string non è terminato da null, quindi è consentita un'implementazione (e probabilmente lo farà) restituendo un nuovo array allocato di const char. Se la creazione di std::string non è inclusa nel campo di validità o se è stata modificata, la stringa c_str() restituita non è valida.

  2. data() restituisce i dati, ma attenzione che non sia una stringa con terminazione null.

In nessuno dei due casi, si suppone di modificare i dati, sia i puntatori data() e c_str() ritorno a const char, e davvero non dovrebbe.

E.g., std::string s possono essere le stringhe conteggiate di riferimento (anche se questo non è più comune) o possono anche utilizzare schemi di indicizzazione funky sui loro dati (mai visto, però).

1

Se si desidera effettivamente i "dati" all'interno della stringa, quindi string::data() è la funzione che si sta cercando.

Nota tuttavia che, come c_str(), è un puntatore const per i dati, non è necessario modificare questi dati.

Problemi correlati