2013-11-01 14 views
5

ho incontrato una domanda in qualche quiz "Is a string a vector? If yes, in what way? If no, why not?" Entrambi hanno accesso casuale ai contenuti. Ma la stringa ha alcuni metodi che vector dosn`t. Può anche avere un conteggio dei riferimenti. Quindi è ovvio che la stringa non è esattamente un vettore (typef string vector) Esistono implementazioni note in cui class string : public vector <char>? In caso negativo - qual è la ragione per non implementarla così?stl - Una stringa è un vettore?

+0

La stringa ha alcuni metodi che vector dosn't? il contrario è vero. –

+0

@MehdiTaxir - per esempio c_str() o data() o find_first_of() ecc. – Yakov

+2

Nota: C++ 11 vieta esplicitamente le stringhe conteggiate di riferimento –

risposta

6

Da un punto di vista puramente filosofico: sì, una stringa è un di tipo di vettore. È un blocco di memoria contiguo che memorizza i caratteri (un vettore è un blocco di memoria contiguo che memorizza oggetti di tipi arbitrari). Quindi, da questa prospettiva, una stringa è un tipo speciale di vettore.

In termini di progettazione e realizzazione di std::string e std::vector, condividono alcuni degli stessi elementi di interfaccia (ad esempio, i blocchi di memoria contigui, operator[]), ma std::string fa non derivano da std::vector (nota a margine: non dovrebbe derivare pubblicamente da contenitori standard in quanto non sono progettati per essere classi basate - ad esempio non hanno distruttori virtuali), né sono direttamente convertibili l'uno con l'altro. Cioè, il seguente non verrà compilato:

std::string s = "abc"; 
std::vector<char> v = s; // ERROR! 

Tuttavia, dal momento che entrambi hanno il supporto iteratore, è possibile convertire una stringa in un vettore:

std::string s = "abc"; 
std::vector<char> v(s.begin(), s.end()); // note that the vector will NOT include the '\0' character 

std::string non avrà più un conteggio di riferimento (come in C++ 11) come funzionalità di copia su scrittura che molte implementazioni utilizzate erano proibite dallo standard C++ 11.

Dal punto di vista della memoria, un'istanza di std::string sarà molto simile ad un std::vector<char> (es entrambi avranno un puntatore alla loro posizione di memoria, una dimensione, una capacità), ma la funzionalità delle due classi è diverso.

+0

"non si dovrebbe prelevare pubblicamente dai contenitori standard in quanto non hanno distruttori virtuali". Hmm, penso che sia ampiamente vero, ma ci soffermiamo un po 'su. Inserirò un po 'di testo nel mezzo: "Non dovresti discuterne pubblicamente dai contenitori standard perché non sono progettati per essere usati come classi base, un indizio è che non hanno distruttori virtuali". Non è l'unica ragione, e non è interamente una ragione in sé. – BoBTFish

+0

@BoBTFish Buon punto. Regolerò la formulazione. –

+0

Solo un pelo sul vocabolario, ma un vettore non memorizza i tipi, memorizza oggetti di tipo arbitrario. (Più o meno: gli oggetti devono essere copiabili, per esempio.) –

10

std::string ha una parte non banale della sua interfaccia in comune con std::vector (e altri contenitori standard), ma è decisamente una cosa diversa, con uno scopo diverso.

Può anche essere implementato in modo molto diverso, in quanto consente di eseguire operazioni come l'ottimizzazione della stringa piccola o la copia su scrittura (non legale dal 2011). (Anche se è certamente possibile per loro avere implementazioni molto simili).

Entrambi supportano gli iteratori di accesso casuale, quindi possono essere utilizzati in modo simile con algoritmi standard. I thinkstd::string non può essere classificato come contenitore di sequenza.

Non sarebbe possibile realizzare molte delle funzioni membro std::string s' direttamente ereditando da std::vector, perché nasconde il fatto che è anche immagazzinata -terminator NUL. Pertanto, quando std::string::size restituisce 3, std::vector::size restituisce 4, ad esempio. Lo stesso vale per end e pochi altri.

3

No, std::string (std::basic_string<char>), si può pensare che un tipo di contenitore sequenza che contiene char in quanto ne condivide molte funzioni con altri contenitori, ma non è implementato utilizzando std::vector.

3

Il motivo principale per cui non è possibile (o almeno certamente non dovrebbe essere) implementato utilizzando l'ereditarietà pubblica è che non è consentita la conversione implicita da string a vector. Ad esempio, se scrivo un codice simile:

int f(std::vector<char> const &s); 

// ... 

std::string s; 
f(s); 

Compilation dovesse fallire (in assenza di qualche altro sovraccarico f che accetta un string).

Se si voleva davvero, si potrebbe (probabilmente) fare una legittima applicazione della std::string usando privato eredità da std::vector però. Potrebbe non essere il più efficiente possibile, ma almeno a mano a mano, non riesco a pensare a un requisito che ovviamente violerebbe. La perdita di efficienza sarebbe dovuta al fatto che è necessario che std::vector sia un po 'più generale - deve supportare l'istanza su tipi che possono generare eccezioni, mentre std::string è progettato solo per essere istanziato su tipi che sono esenti da eccezioni.

+0

Un altro motivo per cui non è possibile implementare l'ereditarietà pubblica è la mancanza di un distruttore virtuale (per qualsiasi contenitore std). –

+0

@ZacHowland L'idea è che suppongo che l'ereditarietà sarebbe solo un dettaglio di implementazione che nessun utente potrebbe conoscere, quindi non memorizzerebbe mai uno 'std :: vector *' a un 'std :: string', e certamente non cancellarlo. – BoBTFish

Problemi correlati