2009-08-17 18 views
90

Conosco un po 'di C e ora sto dando un'occhiata a C++. Sono abituato a char array per trattare con stringhe C, ma mentre guardo codice C++ Vedo che ci sono esempi che utilizzano entrambi tipo e char stringa array:Differenza tra i tipi string e char [] in C++

#include <iostream> 
#include <string> 
using namespace std; 

int main() { 
    string mystr; 
    cout << "What's your name? "; 
    getline (cin, mystr); 
    cout << "Hello " << mystr << ".\n"; 
    cout << "What is your favorite team? "; 
    getline (cin, mystr); 
    cout << "I like " << mystr << " too!\n"; 
    return 0; 
} 

e

#include <iostream> 
using namespace std; 

int main() { 
    char name[256], title[256]; 

    cout << "Enter your name: "; 
    cin.getline (name,256); 

    cout << "Enter your favourite movie: "; 
    cin.getline (title,256); 

    cout << name << "'s favourite movie is " << title; 

    return 0; 
} 

(entrambi gli esempi da http://www.cplusplus.com)

Suppongo che questa sia una domanda largamente richiesta e ovvia (ovvia? , API i integrazione, il modo in cui ognuno è migliore, ...).

Grazie.

+0

Questo può aiutare: [C++ char * vs std :: string] (http://stackoverflow.com/questions/801209/c-char-vs-stdstring) –

risposta

140

Un array di char è solo che - un array di caratteri:

  • Se allocato sullo stack (come nel tuo esempio), sarà sempre occupare es. 256 byte indipendentemente dalla lunghezza del testo che contiene è
  • Se allocati nell'heap (utilizzando malloc() o new char []) si è responsabili del rilascio della memoria in seguito e si avrà sempre il sovraccarico di un'allocazione dell'heap .
  • Se si copia un testo di più di 256 caratteri nell'array, esso potrebbe bloccarsi, produrre brutti messaggi di asserzione o causare un comportamento inspiegabile (errato) da qualche altra parte nel programma.
  • Per determinare la lunghezza del testo, l'array deve essere scansionato, carattere per carattere, per un carattere \ 0.

Una stringa è una classe che contiene un array di caratteri, ma la gestisce automaticamente per te. La maggior parte delle implementazioni di stringhe hanno un array incorporato di 16 caratteri (quindi le stringhe brevi non frammentano l'heap) e usano l'heap per stringhe più lunghe.

È possibile accedere array di caratteri di una stringa come questa:

std::string myString = "Hello World"; 
const char *myStringChars = myString.c_str(); 

stringhe C++ possono contenere incorporato \ 0 personaggi, sai la loro lunghezza senza contare, sono più veloci di array di char heap-assegnato per testi brevi e si protegge da sovraccarichi del buffer. Inoltre sono più leggibili e più facili da usare.

-

Tuttavia, C++ le stringhe non sono (molto) adatto per l'utilizzo oltre i confini DLL, perché ciò richiederebbe qualsiasi utente di tale funzione DLL per assicurarsi che sta usando la stessa identica compilatore e l'implementazione runtime C++, per non rischiare che la sua classe di corda si comporti diversamente.

Normalmente, una classe string Sarebbe anche rilasciare la sua memoria heap sul mucchio chiamare, quindi sarà solo in grado di liberare di nuovo la memoria se si sta utilizzando un comune (DLL o .so) versione del runtime.

In breve: utilizzare le stringhe C++ in tutte le funzioni e i metodi interni. Se scrivi mai un file .dll o .so, usa le stringhe C nelle tue funzioni pubbliche (dll/so-exposed).

+3

Inoltre, le stringhe hanno un sacco di funzioni di aiuto che possono essere veramente pulite. –

+1

Non credo al bit sui limiti della DLL. In caso di circostanze molto particolari potrebbe potenzialmente interromperlo ((una DLL sta staticamente collegando una versione diversa del runtime a quella utilizzata da altre DLL) e le cose peggiori probabilmente accadono prima in queste situazioni) ma nel caso generale in cui tutti utilizzano il valore predefinito la versione condivisa del runtime standard (l'impostazione predefinita) non si verificherà. –

+1

Esempio: distribuisci binari compilati da VC2008SP1 di una libreria pubblica chiamata libfoo, che ha una std :: string & nella sua API pubblica. Ora qualcuno scarica il tuo libfoo.dll e fa una build di debug. La sua std :: string potrebbe avere alcuni campi di debug aggiuntivi, causando lo spostamento del puntatore per lo spostamento delle stringhe dinamiche. – Cygon

6

Bene, il tipo stringa è una classe completamente gestita per le stringhe di caratteri, mentre char [] è ancora ciò che era in C, una matrice di byte che rappresenta una stringa di caratteri per te.

In termini di API e libreria standard, tutto viene implementato in termini di stringhe e non di char [], ma ci sono ancora molte funzioni dalla libc che riceve char [] quindi potrebbe essere necessario usarlo per quelle, a parte da quello userei sempre std :: string.

In termini di efficienza, naturalmente, un buffer non elaborato della memoria non gestita sarà quasi sempre più veloce per molte cose, ma prendere in considerazione il confronto delle stringhe, ad esempio, std :: string ha sempre le dimensioni per controllarlo prima, mentre con char [] è necessario confrontare carattere per carattere.

6

Arkaitz è corretto che string è un tipo gestito. Ciò significa che per è che non devi mai preoccuparti di quanto è lunga la stringa, né devi preoccuparti di liberare o riallocare la memoria della stringa.

D'altra parte, la notazione char[] nel caso precedente ha limitato il buffer dei caratteri a esattamente 256 caratteri. Se provi a scrivere più di 256 caratteri in quel buffer, nella migliore delle ipotesi sovrascrivi la memoria che il tuo programma "possiede". Nel peggiore dei casi, tenterai di sovrascrivere la memoria che non possiedi e il tuo sistema operativo ucciderà il tuo programma sul posto.

Bottom line? Le stringhe sono molto più programmabili, i caratteri [char] sono molto più efficienti per il computer.

+3

Nel peggiore dei casi, altre persone sovrascriveranno la memoria ed eseguiranno codice dannoso sul tuo computer. Vedi anche [buffer overflow] (http://cwe.mitre.org/data/definitions/120.html). –

5

Personalmente non vedo alcun motivo per cui si vorrebbe usare char * o char [] tranne per compatibilità con il vecchio codice. std :: string non è più lento di usare una c-string, tranne che gestirà la ridistribuzione per te. È possibile impostare la sua dimensione quando lo si crea, e quindi evitare la ridistribuzione, se lo si desidera. L'operatore di indicizzazione ([]) fornisce un accesso costante al tempo (ed è nel vero senso della parola esattamente la stessa cosa che usare un indicizzatore di stringa c). Usare il metodo at ti dà anche sicurezza sui limiti, qualcosa che non ottieni con le stringhe, a meno che tu non lo scriva. Molto spesso il compilatore ottimizza l'uso dell'indicizzatore in modalità di rilascio. È facile scherzare con c-stringhe; cose come delete vs delete [], sicurezza delle eccezioni, persino come riallocare una c-string.

E quando si ha a che fare con concetti avanzati come avere stringhe COW, e non-COW per MT ecc., Occorrerà std :: string.

Se siete preoccupati per le copie, fino a quando si utilizzano i riferimenti e riferimenti const ovunque è possibile, non avrete alcun sovraccarico a causa di copie, ed è la stessa cosa che si sarebbe fare con il c-string .

+0

+1 Anche se non hai considerato problemi di implementazione come la compatibilità con DLL, hai ottenuto COW. –

+0

e che ne so che il mio array di caratteri in 12 byte? Se creo un'istanza per una stringa, potrebbe non essere davvero efficace, giusto? –

+0

@David: se si dispone di un codice estremamente sensibile alla perfezione, allora sì. Potresti considerare std :: string ctor call come overhead oltre all'inizializzazione dei membri std :: string. Ma ricorda che l'ottimizzazione prematura ha reso inutilizzabili molte basi di codice, quindi fai attenzione. – Abhay

0

Pensate a (char *) come string.begin(). La differenza essenziale è che (char *) è un iteratore e std :: string è un contenitore. Se ti attieni alle stringhe di base un (char *) ti darà quello che fa std :: string :: iterator. È possibile utilizzare (char *) quando si desidera il beneficio di un iteratore e anche la compatibilità con C, ma questa è l'eccezione e non la regola. Come sempre, fai attenzione all'invalidità dell'iteratore. Quando la gente dice (char *) non è sicuro, questo è ciò che intendono dire. È sicuro come qualsiasi altro iteratore C++.

1

Le stringhe dispongono di funzioni di supporto e gestiscono automaticamente gli array di vettori. È possibile concatenare stringhe, per un array di caratteri che è necessario copiarlo in un nuovo array, le stringhe possono modificarne la lunghezza in fase di esecuzione. Un array di caratteri è più difficile da gestire rispetto a una stringa e alcune funzioni possono accettare solo una stringa come input, richiedendo la conversione della matrice in una stringa. È meglio usare le stringhe, sono state create in modo da non dover utilizzare array. Se gli array fossero oggettivamente migliori, non avremmo stringhe.

0

Una delle differenze è la terminazione Null (\ 0).

In C e C++, char * o char [] assegna un puntatore a un singolo carattere come parametro e traccia lungo la memoria fino a quando non viene raggiunto un valore di memoria 0 (spesso chiamato terminatore null).

Le stringhe C++ possono contenere caratteri \ 0 incorporati, conoscere la loro lunghezza senza contare.

#include<stdio.h> 
#include<string.h> 
#include<iostream> 

using namespace std; 

void NullTerminatedString(string str){ 
    int NUll_term = 3; 
    str[NUll_term] = '\0';  // specific character is kept as NULL in string 
    cout << str << endl <<endl <<endl; 
} 

void NullTerminatedChar(char *str){ 
    int NUll_term = 3; 
    str[NUll_term] = 0;  // from specific, all the character are removed 
    cout << str << endl; 
} 

int main(){ 
    string str = "Feels Happy"; 
    printf("string = %s\n", str.c_str()); 
    printf("strlen = %d\n", strlen(str.c_str())); 
    printf("size = %d\n", str.size()); 
    printf("sizeof = %d\n", sizeof(str)); // sizeof std::string class and compiler dependent 
    NullTerminatedString(str); 


    char str1[12] = "Feels Happy"; 
    printf("char[] = %s\n", str1); 
    printf("strlen = %d\n", strlen(str1)); 
    printf("sizeof = %d\n", sizeof(str1)); // sizeof char array 
    NullTerminatedChar(str1); 
    return 0; 
} 

uscita:

strlen = 11 
size = 11 
sizeof = 32 
Fee s Happy 


strlen = 11 
sizeof = 12 
Fee 
+0

Nota che stai rispondendo a una domanda posta 8 anni fa. –

+0

@ n.m: si lo so. quando sto attraversando, la maggior parte dei punti sono trattati in questo e ho aggiunto un altro punto che aiuterà a ottenere tutte le risposte (al massimo) in un posto. –

Problemi correlati