Qual è la differenza fondamentale, se esiste, tra un C++ std :: vector e std :: basic_string?Vector vs stringa
risposta
Un vettore è una struttura di dati che simula una matrice. Nel profondo è in realtà una matrice (dinamica).
La classe basic_string rappresenta una sequenza di caratteri. Contiene tutte le normali operazioni di una sequenza e, inoltre, contiene operazioni di stringa standard come la ricerca e la concatenazione.
È possibile utilizzare il vettore per mantenere qualsiasi tipo di dati desiderato std::vector<int> or <float> or even std::vector< std::vector<T> >
ma uno basic_string
può essere utilizzato solo per rappresentare "testo".
Sono sicuro che potrei trovare un modo per fare una 'basic_string' piena di doppi o qualcosa di altrettanto malvagio e che in effetti" funziona ". –
Bene, molte implementazioni implementano 'basic_string' in termini di qualcosa come' vector'. E qualsiasi tipo per cui è definita una classe 'char_traits' funzionerà con' std :: basic_string', anche se hai creato un 'char_traits
@Billy - non vero. Alcune delle stesse tecniche potrebbero essere utilizzate in entrambi, ma non ho mai visto un 'basic_string' implementato in termini di' vector'. In effetti, un'implementazione molto comune, distribuita con MSVC++, è MOLTO diversa in quanto utilizzano l'ottimizzazione della stringa piccola (qualsiasi cosa abbastanza piccola da adattarsi a un puntatore è semplicemente bloccata nel puntatore al buffer anziché allocarla). –
La stringa di base fornisce molte opzioni di confronto specifiche per le stringhe. Hai ragione nel senso che l'interfaccia di gestione della memoria sottostante è molto simile, ma la stringa contiene molti membri aggiuntivi, come c_str(), che non avrebbe senso per un vettore.
Non penso che esista un vettore che utilizza l'ottimizzazione delle stringhe di piccole dimensioni. Non sono uscito a cercarne uno, ma sono abbastanza sicuro che non è là fuori. Non sarebbe così utile. La verità è che le due cose sono semplicemente differenti. Hanno scopi diversi e spesso vengono implementati MOLTO diversamente, sebbene un approccio ingenuo possa essere simile in entrambi. –
@ Noah: ecco perché ho detto "interfaccia". – Puppy
Quali confronti sono specifici per le stringhe? Dato che il tipo di dati dell'elemento è variabile in entrambi i casi, le cose come il confronto lessicografico hanno tanto senso per i vettori quanto le stringhe. Naturalmente un confronto senza distinzione tra maiuscole e minuscole sarebbe una stringa specifica, ma la stringa non sarebbe polimorfica. – Yttrill
La differenza chiave è che std::vector
dovrebbe mantenere i propri dati in memoria continua, quando std::basic_string
non è in grado di. Di conseguenza:
std::vector<char> v('a', 3);
char* x = &v[0]; // valid
std::basic_string<char> s("aaa");
char* x2 = &s[0]; // doesn't point to continuous buffer
//For example, the behavior of
std::cout << *(x2+1);
//is undefined.
const char* x3 = s.c_str(); // valid
Err ... quell'esempio di codice è perfettamente valido.Ora se hai modificato 'x2' usando l'aritmetica del puntatore è possibile che non sia valido (dipende dal tuo compilatore), ma non sono a conoscenza di nessun compilatore che lo faccia. –
Non sono a conoscenza di questo compilatore, ma non dovresti contare su quel 'x2' punta al buffer continuo, perché lo standard C++ non fornisce alcuna garanzia. –
Nessuno di questi è effettivamente valido. Nessuno dei due oggetti ha alcuna dimensione e quindi il primo elemento è in realtà uno dopo la fine e non è possibile dereferenziare quell'elemento. Solo quello c_str() è ben definito. –
basic_string
dà compilatore e le implementazioni della libreria standard, qualche libertà oltre vettore:
L ' "ottimizzazione piccola stringa" è valida sulle corde, che permette implementazioni per memorizzare la stringa effettiva, piuttosto che un puntatore alla stringa, nell'oggetto stringa quando la stringa è breve. Qualcosa sulla falsariga di:
class string { size_t length; union { char * usedWhenStringIsLong; char usedWhenStringIsShort[sizeof(char*)]; }; };
In C++ 03, la matrice sottostante non deve essere contiguo. L'implementazione di
basic_string
in termini di qualcosa come una "corda" sarebbe possibile secondo lo standard corrente. (Anche se nessuno lo fa perché ciò renderebbe i membristd::basic_string::c_str()
estd::basic_string::data()
troppo costosi da implementare.)
C++ 11 ora vieta questo comportamento.In C++ 03,
basic_string
permette l'/ fornitore libreria compilatore di utilizzare copy-on-write per i dati (che può risparmiare sulle copie), che non è consentito perstd::vector
. In pratica, questo era molto più comune, ma al giorno d'oggi è meno comune a causa dell'impatto che ha sul multithreading. In ogni caso, il tuo codice non può fare affidamento sul fatto che lostd::basic_string
sia implementato o meno usando COW.
Ora C++ 11 vieta nuovamente questo comportamento.
ci sono un paio di metodi di supporto appiccicato al basic_string
pure, ma la maggior parte sono semplici e, naturalmente, potrebbe essere facilmente implementato in cima vector
.
Non mi piace pensare (1) come motivo per scegliere o utilizzare std :: string è un effetto indesiderato sul lato del testo standard che è stato rafforzato nel nuovo standard. (2) era una buona ragione per usare std :: string perché rendeva le stringhe di ritorno dai metodi molto efficienti (praticamente senza alcun costo), purtroppo questo viene rimosso a causa dei requisiti per il parallelismo (sebbene dalla lettura del documento che lo consiglia, sembra corda prenderà il mantello di COW alla fine (dovremo aspettare e vedere se funziona) –
@Martin: Questo è vero. La semantica di spostamento OTOH elimina molti dei casi in cui le implementazioni di COW hanno accelerato le cose :) –
basic_string non chiama costruttori e distruttori dei suoi elementi. il vettore sì.
swapping basic_string invalida gli iteratori (consentendo l'ottimizzazione di stringhe di piccole dimensioni), lo scambio di vettori non lo fa.
La memoria di base_string non può essere allocata continuamente in C++ 03. il vettore è sempre continuo. Questa differenza viene rimosso in C++ 0x [string.require]:
Gli oggetti char-simili in un oggetto basic_string sono memorizzati in modo contiguo
basic_string ha interfaccia per operazioni di stringa. il vettore no.
basic_string può utilizzare la copia sulla strategia di scrittura (in pre C++ 11). il vettore non può.
citazioni rilevanti per i non credenti:
[basic.string]:
Il modello di classe basic_string è conforme ai requisiti per un contenitore di sequenza (23.2.3), per un Reversible Container (23.2), e per un contenitore di Allocator-aware (Tabella 99), ad eccezione del fatto che basic_string non costruisce o distrugge i suoi elementi utilizzando allocator_traits :: construct e allocator_- tratti: destroy e that swap() per basic_string invalida gli iteratori. Gli iteratori supportati da di basic_string sono iteratori ad accesso casuale (24.2.7).
@Billy: leggi lo standard prima del downvoting, ho aggiunto la citazione. – ybungalobill
Per quanto posso dire, quella citazione non proviene da 'lo standard' ma dalla bozza C++ 0x. Va bene e vale la pena menzionarlo, ma è necessario qualificarlo con "In C++ 0x ...". – GManNickG
@GMan: Hmm, sembra che tu abbia ragione. Ma solo la formulazione è diversa, il C++ 98 dice ancora che assegna e rilascia gli elementi solo. Questo cambiamento è solo un chiarimento. – ybungalobill
Una differenza tra std::string
e std::vector
è che i programmi possono costruire una stringa da una stringa con terminazione null, mentre con vettori non possono.
Questo spesso rende le stringhe più facili da utilizzare.
TLDR: string
s sono ottimizzati per contenere solo primitivi caratteri, vector
s possono contenere primitive o oggetti
La differenza preminente tra vector
e string
è che vector
possono contenere correttamente oggetti, string
funziona solo su primitive. Così vector
fornisce questi metodi che sarebbero inutili per un string
lavorare con primitive:
Anche estendentesi string
non gli permetterà di gestire correttamente oggetti, perché manca un distruttore.Questo non deve essere visto come uno svantaggio, che consente di ottimizzare notevole su vector
in quel string
può:
- fare short string optimization, potenzialmente evitando allocazione heap, con little-no increased storage overhead
- Usa
char_traits
, uno dei templatestring
s' argomenti, per definire come operazioni devono essere implementati su primitive contenute (di cui solochar
,wchar_t
,char16_t
echar32_t
sono implementate: http://en.cppreference.com/w/cpp/string/char_traits)
Particolarmente rilevanti sono char_traits::copy
, char_traits::move
e char_traits::assign
che implicano ovviamente che l'assegnazione diretta, piuttosto che la costruzione o la distruzione, verrà utilizzata nuovamente, preferibile per le primitive. Tutto ciò specializzazione presenta gli inconvenienti aggiuntivi per string
che:
- Solo
char
, saranno utilizzatiwchar_t
,char16_t
ochar32_t
tipi primitivi. Ovviamente, le primitive di dimensioni fino a 32-bit, potrebbero utilizzare il loro equivalente di dimensionichar_type
: https://stackoverflow.com/a/35555016/2642059, ma per primitive comelong long
avrebbe bisogno di essere scritta una nuova specializzazione dichar_traits
, e l'idea di specializzarsichar_traits::eof
echar_traits::not_eof
invece di usarevector<long long>
non sembra il miglior uso del tempo. - A causa di ottimizzazione stringa breve, iteratori sono invalidate da tutte le operazioni che potrebbero invalidare un iteratore
vector
, mastring
iteratori sono inoltre invalidato dastring::swap
estring::operator=
differenze supplementare nelle interfacce di vector
e string
:
- non v'è mutabile
string::data
: Why Doesn't std::string.data() provide a mutable char*? string
fornisce la funzionalità per lavorare con parole non disponibili invector
:string::c_str
,string::length
,string::append
,string::operator+=
,string::compare
,string::replace
,string::substr
,string::copy
,string::find
,string::rfind
,string::find_first_of
,string::find_first_not_of
,string::flind_last_of
,string::find_last_not_of
,string::operator+
,string::operator>>
,string::operator<<
,string::stoi
,string::stol
,string::stoll
,string::stoul
,string::stoull
,string::stof
,string::stod
,string::stold
,stirng::to_string
,string::to_wstring
- Infine ovunque
vector
accetta argomenti di un'altravector
,string
accetta unstring
o unchar*
Nota che questa risposta è scritta nei confronti C++ 11, in modo da string
s sono tenuti ad essere allocato in modo contiguo.
- 1. vector :: al vs. vector :: operator []
- 2. Sparse Vector vs Dense Vector
- 3. Vector vs prestazioni SynchronizedList
- 4. Vector clear vs. ridimensiona
- 5. vector <unsigned char> vs stringa per dati binari
- 6. Clojure list vs. vector vs. set
- 7. Vector sottoinsiemi vs. Lista sottoinsiemi
- 8. Vector. <> Vs array
- 9. C++ Vector vs Array (Time)
- 10. std :: vector vs normal array
- 11. Frame Vector vs. Data in R
- 12. std :: list vs std :: vector iteration
- 13. MapBox MB Tile vs Vector Tile
- 14. Vector vs. ArrayList che è meglio?
- 15. std :: vector :: cancellare vs "swap e pop"
- 16. Markers vs. Vector point - impatto sulle prestazioni
- 17. C++ std :: vector emplace vs insert
- 18. Cos'è la tupla? E tuple contro List vs. Vector?
- 19. Supporto Vector Machine vs K Vicini vicini più vicini
- 20. NULL vs stringa vuota
- 21. String vs stringa
- 22. string.decode() vs. unicode (stringa)
- 23. Stringa rapida tramite stringa letterale vs inizializzatore
- 24. Come costruire una stringa: std :: vector <string>?
- 25. Inizializzazione Eigen :: vector con std :: vector
- 26. std :: vector or boost :: vector thread safe?
- 27. Formattazione stringa Python:% vs concatenazione
- 28. Asp.Net Mvc: ContentResult vs. stringa
- 29. Iterator vs. Reference vs. pointer
- 30. convert <vector><string> TO <vector><int> C++, Win32
Controllare i documenti, hanno interfacce diverse. Se hai specificato il problema che stai risolvendo, le risposte potrebbero essere anche più specifiche. –
@Gene: hanno interfacce diverse, ma entrambe implementano tutto il necessario per essere un contenitore di sequenza STL. –
@Gene: Non sto risolvendo alcun problema particolare, sono solo curioso di sapere perché dovrei scegliere l'uno o l'altro per vari scopi: non sto contando l'esistenza di alcuni metodi simili a stringhe come fondamentali. Neanche io considero le prestazioni come fondamentali. Comunque la validità degli iteratori è sicuramente confermata da diverse risposte. E ho il vago sospetto che il tipo di dati per una stringa debba avere un valore "Zero come" per mettere il metodo di fine data() (ottenuto da un thingy tratti). – Yttrill