Quali prestazioni possiamo aspettarci da std :: string's c_str ()? Tempo sempre costante?

11

Ultimamente ho fatto alcune ottimizzazioni necessarie. Una cosa che ho fatto è cambiare alcuni stream di ostrings - > sprintfs. Sto sprintf'ing un gruppo di std :: stringhe in un array in stile c, ala

char foo[500];
sprintf(foo, "%s+%s", str1.c_str(), str2.c_str());

Si scopre che l'implementazione di Microsoft std :: string :: c_str () viene eseguita in tempo costante (restituisce semplicemente un puntatore interno). Sembra che libstdc ++ faccia lo stesso . Mi rendo conto che std non offre garanzie per c_str, ma è difficile immaginare un altro modo per farlo. Se, ad esempio, copiavano in memoria, dovevano allocare memoria per un buffer (lasciandolo al chiamante per distruggerlo - NON fa parte del contratto STL) O dovevano copiare su un file statico interno buffer (probabilmente non a prova di thread, e non hai garanzie sulla sua durata). Quindi semplicemente restituire un puntatore a una stringa terminata da null internamente mantenuta sembra essere l'unica soluzione realistica.

    
posta Doug T. 13.12.2011 - 04:09
fonte

3 risposte

8

Se ricordo, lo standard consente a string::c_str() di restituire praticamente tutto ciò che soddisfa:

  • Memoria che è abbastanza grande per il contenuto della stringa e il% co_de terminante
  • Deve essere valido fino a quando un membro non-const dell'oggetto NULL è chiamato

Quindi, in pratica, questo significa un puntatore alla memoria interna; in quanto non c'è modo di tracciare esternamente la vita del puntatore restituito. Penso che la tua ottimizzazione sia sicura assumendo che questo è (piccolo) un tempo costante.

Su una nota correlata, se la formattazione della stringa è una limitazione delle prestazioni; si può trovare una migliore fortuna rimandando la valutazione fino a quando assolutamente necessario con qualcosa come Boost.Phoenix .

string Credo che rimuova la formattazione internamente fino a che non sia richiesto il risultato, e puoi usare ripetutamente lo stesso oggetto formato senza ripetere l'analisi della stringa di formato, che ho trovato fare una differenza significativa per la registrazione ad alta frequenza .

    
risposta data 13.12.2011 - 04:44
fonte
22

Nello standard c ++ 11 (sto leggendo la versione N 3290), il capitolo 21.4.7.1 parla del metodo c_str ():

const charT* c_str() const noexcept; const charT* data() const noexcept;

Returns: A pointer p such that p + i == &operator for each i in [0,size()].
Complexity: constant time.
Requires: The program shall not alter any of the values stored in the character array.

Quindi, sì: la complessità del tempo costante è garantita dallo standard.

Ho appena controllato lo standard c ++ 03, e non ha tali requisiti, né dice la complessità.

    
risposta data 13.12.2011 - 12:43
fonte
7

In teoria, C ++ 03 non richiede questo, e quindi la stringa può essere una matrice di caratteri in cui viene aggiunta la presenza del terminatore null proprio nel momento in cui viene chiamato c_str (). Questo potrebbe richiedere una riallocazione (non viola la costanza, se il puntatore privato interno è dichiarato come mutable ).

C ++ 11 è più severo: richiede una certa costanza di tempo, quindi non può essere eseguito alcun riposizionamento e la matrice deve essere sempre sufficientemente ampia da memorizzare il valore null alla fine. c_str (), di per sé, può ancora fare " ptr[size()]='[0..size())' " per assicurare che il null sia realmente presente. Non viola la costanza dell'array poiché l'intervallo %code% non viene modificato.

    
risposta data 14.12.2011 - 17:43
fonte

Leggi altre domande sui tag