Domanda

Quando dovrei usare std::string e quando dovrei usare char* per gestire array di char s in C ++?

Sembra che dovresti usare <=> se le prestazioni (velocità) sono cruciali e sei disposto ad accettare alcune attività rischiose a causa della gestione della memoria.

Ci sono altri scenari da considerare?

È stato utile?

Soluzione

Puoi passare std :: stringhe per riferimento se sono grandi per evitare la copia, o un puntatore all'istanza, quindi non vedo alcun vantaggio reale usando i puntatori char.

Uso std :: string / wstring per più o meno tutto ciò che è testo reale. char * è utile per altri tipi di dati e puoi essere sicuro che venga deallocato come dovrebbe. Altrimenti std :: vector è la strada da percorrere.

Probabilmente ci sono eccezioni a tutto ciò.

Altri suggerimenti

Il mio punto di vista è:

  • Non usare mai char * se non si chiama " C " codice.
  • Usa sempre std :: string: è più facile, è più amichevole, è ottimizzato, è standard, ti impedirà di avere bug, è stato verificato e dimostrato di funzionare.

Utilizzo di stringhe non elaborate

Sì, a volte puoi davvero farlo. Quando si utilizza const char *, gli array di caratteri allocati nello stack e i valori letterali delle stringhe è possibile farlo in modo tale che non vi sia alcuna allocazione di memoria.

Scrivere un tale codice richiede spesso più pensiero e cura che usare una stringa o un vettore, ma con le tecniche appropriate può essere fatto. Con le tecniche appropriate il codice può essere sicuro, ma è sempre necessario assicurarsi che durante la copia in char [] si disponga di alcune garanzie sulla lunghezza della stringa che si sta copiando, oppure si controlla e si maneggia con garbo stringhe di grandi dimensioni. Non farlo è ciò che ha dato alla famiglia di funzioni strcpy la reputazione di non essere sicuro.

Come i modelli possono aiutare a scrivere buffer di caratteri sicuri

Per quanto riguarda la sicurezza dei buffer char [], i template possono aiutare, in quanto possono creare un incapsulamento per gestire le dimensioni del buffer. Modelli come questo sono implementati ad es. da Microsoft per fornire sostituzioni sicure per strcpy. L'esempio qui è estratto dal mio codice, il codice reale ha molti più metodi, ma questo dovrebbe essere sufficiente per trasmettere l'idea di base:

template <int Size>
class BString
{
  char _data[Size];

  public:
  BString()
  {
    _data[0]=0;
    // note: last character will always stay zero
    // if not, overflow occurred
    // all constructors should contain last element initialization
    // so that it can be verified during destruction
    _data[Size-1]=0;
  }
  const BString &operator = (const char *src)
  {
    strncpy(_data,src,Size-1);
    return *this;
  }

  operator const char *() const {return _data;}
};

//! overloads that make conversion of C code easier 
template <int Size>
inline const BString<Size> & strcpy(BString<Size> &dst, const char *src)
{
  return dst = src;
}

Un'occasione che DEVI usare char* e non std::string è quando hai bisogno di costanti di stringhe statiche. Il motivo è che non hai alcun controllo sui moduli di ordine per inizializzare le loro variabili statiche e un altro oggetto globale di un modulo diverso può fare riferimento alla tua stringa prima che sia inizializzata. http://google-styleguide.googlecode.com/svn/trunk/ cppguide.xml # Static_and_Global_Variables

<=> pro:

  • gestisce la memoria per te (la stringa può crescere e l'implementazione ti assegnerà un buffer più grande)
  • Interfaccia di programmazione di livello superiore, funziona bene con il resto di STL.

<=> contro: - due istanze di stringa STL distinte non possono condividere lo stesso buffer sottostante. Quindi se passi per valore ottieni sempre una nuova copia. - c'è una penalità per le prestazioni, ma direi che se le tue esigenze sono speciali è trascurabile.

Dovresti considerare di utilizzare char* nei seguenti casi:

  • Questo array verrà passato nel parametro.
  • Conosci in anticipo la dimensione massima del tuo array (lo sai O lo imponi).
  • Non effettuerai alcuna trasformazione su questo array.

In realtà, in C ++, <=> sono spesso usati per piccole parole fisse, come opzioni, nome del file, ecc ...

Quando utilizzare un c ++ std :: string:

  • le stringhe, nel complesso, sono più sicure di char *, normalmente quando fai cose con char * devi controllare le cose per assicurarti che le cose siano giuste, nella classe di stringhe tutto questo è fatto per te.
  • Di solito quando si usa char *, è necessario liberare la memoria allocata, non è necessario farlo con stringa poiché libererà il suo buffer interno quando viene distrutto.
  • Le stringhe funzionano bene con stringstream di c ++, l'IO formattato è molto semplice.

Quando utilizzare char *

  • L'uso di char * ti dà un maggiore controllo su ciò che sta accadendo " dietro " le scene, il che significa che puoi regolare la performance se necessario.

Usa (const) char * come parametri se stai scrivendo una libreria. Le implementazioni std :: string differiscono tra i diversi compilatori.

Se vuoi usare le librerie C, dovrai occuparti delle stringhe C. Lo stesso vale se si desidera esporre l'API a C.

Puoi aspettarti che la maggior parte delle operazioni su una stringa std :: string (come ad esempio find) sia il più ottimizzata possibile, quindi è probabile che eseguano almeno così come una controparte C.

Vale anche la pena notare che gli iteratori std :: string abbastanza spesso eseguono il mapping ai puntatori nell'array char sottostante. Quindi, qualsiasi algoritmo che concepisci su iteratori è essenzialmente identico allo stesso algoritmo su char * in termini di prestazioni.

Le cose a cui prestare attenzione sono ad es. operator[] - la maggior parte delle implementazioni STL non esegue il controllo dei limiti e deve tradurlo nella stessa operazione sull'array di caratteri sottostante. AFAIK STLPort può facoltativamente eseguire il controllo dei limiti, a quel punto questo operatore sarebbe un po 'più lento.

Quindi cosa ti guadagna usando std :: string? Ti assolve dalla gestione manuale della memoria; il ridimensionamento dell'array diventa più semplice e generalmente devi pensare meno alla liberazione della memoria.

Se sei preoccupato per le prestazioni quando ridimensioni una stringa, c'è una funzione reserve che potresti trovare utile.

se stai usando la matrice di caratteri in testo simile, ecc. usa std :: string più flessibile e più facile da usare. Se lo usi per qualcos'altro come l'archiviazione dei dati? usa array (preferisci i vettori)

Anche quando le prestazioni sono fondamentali, è meglio utilizzare vector<char>: consente l'allocazione anticipata della memoria (metodo reserve ()) e consente di evitare perdite di memoria. L'uso di vector :: operator [] comporta un sovraccarico, ma è sempre possibile estrarre l'indirizzo del buffer e indicizzarlo esattamente come se fosse un carattere *.

AFAIK internamente la maggior parte std :: string implementa la copia in scrittura, la semantica ha contato il riferimento per evitare il sovraccarico, anche se le stringhe non sono passate per riferimento.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top