Regole di invalidazione iteratore


543

Quali sono le regole di invalidazione dell'iteratore per i contenitori C ++?

Preferibilmente in un formato elenco riepilogativo.

(Nota: questo dovrebbe essere una voce alle FAQ C ++ di Stack Overflow . Se vuoi criticare l'idea di fornire una FAQ in questo modulo, allora la pubblicazione su meta che ha iniziato tutto questo sarebbe il posto dove farlo. tale domanda viene monitorata nella chatroom di C ++ , dove l'idea FAQ è iniziata in primo luogo, quindi è molto probabile che la tua risposta venga letta da coloro che hanno avuto l'idea.)


Le risposte devono essere nello stesso formato della risposta?
PW

@PW IMO che sarebbe preferito per la simmetria ma non posso farla rispettare: P
Razze di leggerezza in orbita

che dire di c ++ 20?
Walter,

1
@Walter non esiste ancora;)
Razze di leggerezza in orbita

Questa domanda è, per citare Leela di Futurama, di epoche stupide, e secondo la mia modesta opinione dovrebbe essere lasciata aperta.
Roman Luštrik,

Risposte:


112

C ++ 17 (Tutti i riferimenti provengono dalla bozza di lavoro finale di CPP17 - n4659 )


Inserimento

Contenitori di sequenza

  • vector: Le funzioni insert, emplace_back, emplace, push_backcausa riallocazione se il nuovo formato è maggiore del precedente capacità. La riallocazione invalida tutti i riferimenti, i puntatori e gli iteratori che fanno riferimento agli elementi nella sequenza. Se non si verifica alcuna riallocazione, tutti gli iteratori e i riferimenti prima del punto di inserimento rimangono validi. [26.3.11.5/1]
    Rispetto alla reservefunzione, la riallocazione invalida tutti i riferimenti, i puntatori e gli iteratori che si riferiscono agli elementi nella sequenza. Nessuna riallocazione deve avvenire durante gli inserimenti che si verificano dopo una chiamata reserve()fino al momento in cui un inserimento renderebbe la dimensione del vettore maggiore del valore di capacity(). [26.3.11.3/6]

  • deque: Un inserimento nel mezzo del deque invalida tutti gli iteratori e i riferimenti agli elementi del deque. Un inserimento alle due estremità del deque invalida tutti gli iteratori del deque, ma non ha alcun effetto sulla validità dei riferimenti agli elementi del deque. [26.3.8.4/1]

  • list: Non influisce sulla validità di iteratori e riferimenti. Se viene generata un'eccezione, non ci sono effetti. [26.3.10.4/1].
    Il insert, emplace_front, emplace_back, emplace, push_front, push_backfunzioni Sono compresi in questa regola.

  • forward_list: Nessuno dei sovraccarichi di insert_afterdeve influire sulla validità degli iteratori e dei riferimenti [26.3.9.5/1]

  • array: Di norma , gli iteratori di un array non vengono mai invalidati per tutta la durata dell'array. Si dovrebbe prendere atto, tuttavia, che durante lo scambio, l'iteratore continuerà a puntare allo stesso elemento dell'array e quindi cambierà il suo valore.

Contenitori associativi

  • All Associative Containers: L' inserte emplacemembri non pregiudica la validità degli iteratori e riferimenti al contenitore [26.2.6 / 9]

Contenitori associativi non ordinati

  • All Unordered Associative Containers: Il rehashing annulla gli iteratori, le modifiche all'ordine tra gli elementi e le modifiche in cui compaiono gli elementi bucket, ma non invalida i puntatori o i riferimenti agli elementi. [26.2.7 / 9]
    L' inserte emplacemembri non pregiudica la validità dei riferimenti ad elementi contenitori, ma può invalidare tutti gli iteratori al contenitore. [26.2.7 / 14]
    L' inserte emplacemembri non pregiudica la validità di iteratori se (N+n) <= z * B, dove Nè il numero di elementi nel contenitore prima l'operazione di inserimento, nè il numero di elementi inseriti, Bè conteggio benna del contenitore, ed zè il fattore di carico massimo del contenitore. [26.2.7 / 15]

  • All Unordered Associative Containers: In caso di un'operazione di unione (ad es. a.merge(a2)), Gli iteratori che fanno riferimento agli elementi trasferiti e tutti gli iteratori a cui si fa riferimento asaranno invalidati, ma gli iteratori agli elementi rimanenti a2rimarranno validi. (Tabella 91 - Requisiti del contenitore associativo non ordinato)

Adattatori per container

  • stack: ereditato dal contenitore sottostante
  • queue: ereditato dal contenitore sottostante
  • priority_queue: ereditato dal contenitore sottostante

cancellatura

Contenitori di sequenza

  • vector: Le funzioni erasee pop_backinvalidano iteratori e riferimenti in corrispondenza o dopo il punto della cancellazione. [26.3.11.5/3]

  • deque: Un'operazione di cancellazione che cancella l'ultimo elemento di un dequeinvalida solo l'iteratore passato e tutti gli iteratori e i riferimenti agli elementi cancellati. Un'operazione di cancellazione che cancella il primo elemento di un dequema non l'ultimo invalida solo iteratori e riferimenti agli elementi cancellati. Un'operazione di cancellazione che non cancella né il primo elemento né l'ultimo elemento di un dequeinvalida l'iteratore passato e tutti gli iteratori e i riferimenti a tutti gli elementi di deque. [Nota: pop_fronte pop_backsono operazioni di cancellazione. —End note] [26.3.8.4/4]

  • list: Invalida solo gli iteratori e i riferimenti agli elementi cancellati. [26.3.10.4/3]. Questo vale per erase, pop_front, pop_back, clearfunzioni.
    removee remove_iffunzioni membro: cancella tutti gli elementi dell'elenco a cui fa riferimento un iteratore elenco iper il quale valgono le seguenti condizioni: *i == value, pred(*i) != false. Invalida solo gli iteratori e i riferimenti agli elementi cancellati [26.3.10.5/15].
    uniquefunzione membro - Cancella tutto tranne il primo elemento da ogni gruppo consecutivo di elementi uguali a cui fa riferimento l'iteratore inell'intervallo [first + 1, last)per il quale *i == *(i-1)(per la versione di unique senza argomenti) opred(*i, *(i - 1))(per la versione di unique con un argomento predicato) vale. Invalida solo gli iteratori e i riferimenti agli elementi cancellati. [26.3.10.5/19]

  • forward_list: erase_afterinvalida solo gli iteratori e i riferimenti agli elementi cancellati. [26.3.9.5/1].
    removee remove_iffunzioni membro: cancella tutti gli elementi dell'elenco a cui fa riferimento un iteratore elenco i per il quale valgono le seguenti condizioni: *i == value(per remove()), pred(*i)è vero (per remove_if()). Invalida solo gli iteratori e i riferimenti agli elementi cancellati. [26.3.9.6/12].
    uniquefunzione membro - Cancella tutto tranne il primo elemento da ogni gruppo consecutivo di elementi uguali a cui fa riferimento l'iteratore i nell'intervallo [primo + 1, ultimo) per il quale *i == *(i-1)(per la versione senza argomenti) o pred(*i, *(i - 1))(per la versione con predicato argomento) regge. Invalida solo gli iteratori e i riferimenti agli elementi cancellati. [26.3.9.6/16]

  • All Sequence Containers: clearannulla tutti i riferimenti, i puntatori e gli iteratori che fanno riferimento agli elementi di a e può invalidare l'iteratore passato (tabella 87 - Requisiti del contenitore di sequenze). Ma per forward_list, clearnon invalida gli iteratori del passato. [26.3.9.5/32]

  • All Sequence Containers: assignannulla tutti i riferimenti, i puntatori e gli iteratori che si riferiscono agli elementi del contenitore. Per vectore deque, invalida anche l'iteratore passato. (Tabella 87 - Requisiti del contenitore di sequenze)

Contenitori associativi

  • All Associative Containers: I erasemembri invalidano solo iteratori e riferimenti agli elementi cancellati [26.2.6 / 9]

  • All Associative Containers: I extractmembri invalidano solo gli iteratori sull'elemento rimosso; i puntatori e i riferimenti all'elemento rimosso rimangono validi [26.2.6 / 10]

Adattatori per container

  • stack: ereditato dal contenitore sottostante
  • queue: ereditato dal contenitore sottostante
  • priority_queue: ereditato dal contenitore sottostante

Requisiti generali del contenitore relativi all'invalidazione dell'iteratore:

  • Se non diversamente specificato (esplicitamente o definendo una funzione in termini di altre funzioni), invocare una funzione membro del contenitore o passare un contenitore come argomento a una funzione di libreria non deve invalidare gli iteratori o modificare i valori degli oggetti all'interno di quel contenitore . [26.2.1 / 12]

  • nessuna swap()funzione annulla qualsiasi riferimento, puntatore o iteratore che si riferisce agli elementi dei contenitori che vengono scambiati. [Nota: l'iteratore end () non fa riferimento a nessun elemento, quindi potrebbe essere invalidato. —End note] [26.2.1 / (11.6)]

Come esempi dei requisiti di cui sopra:

  • transformAlgoritmo: L' ope binary_opfunzioni sono iteratori non invalida o sottointervalli, o elementi di comando nella gamme [28.6.4 / 1]

  • accumulatealgoritmo: nell'intervallo [primo, ultimo], binary_opnon deve modificare elementi né invalidare iteratori o subrange [29.8.2 / 1]

  • reducealgoritmo: binary_op non deve invalidare iteratori o subrange, né modificare elementi nell'intervallo [primo, ultimo]. [29.8.3 / 5]

e così via...


7
Oh PW tu eroe!
Razze di leggerezza in orbita

2
@LightnessRacesinOrbit: ho provato a farlo secondo il tuo formato di risposta originale. :)
PW

1
possiamo anche avere un elenco per std::string? Penso che sia diverso da quello std::vectordovuto a SSO
sp2danny il

1
@ sp2danny: a causa di SSO, stringnon soddisfa il secondo requisito generale sopra elencato. Quindi non l'ho incluso. Ha anche cercato di attenersi allo stesso modello delle precedenti voci delle FAQ.
PW

@LightnessRaceswithMonica Grazie ragazzi per il duro lavoro. Ho una domanda che mi confonde per giorni. Cosa significa esattamente "invalidato" in questi contesti? Significa "invalidated" can mean "no longer points to what it used to", not just "may not point to any valid element"come descritto da @Marshall Clow in questa risposta ? O indica solo 1 delle 2 condizioni?
Rick,

410

C ++ 03 (fonte: regole di invalida di Iteratore (C ++ 03) )


Inserimento

Contenitori di sequenza

  • vector: tutti gli iteratori e i riferimenti prima del punto di inserimento non sono interessati, a meno che la dimensione del nuovo contenitore sia maggiore della capacità precedente (nel qual caso tutti gli iteratori e riferimenti sono invalidati) [23.2.4.3/1]
  • deque: tutti gli iteratori e i riferimenti sono invalidati, a meno che l'elemento inserito non si trovi alla fine (fronte o retro) del deque (nel qual caso tutti gli iteratori sono invalidati, ma i riferimenti agli elementi non sono interessati) [23.2.1.3/1]
  • list: tutti gli iteratori e riferimenti non interessati [23.2.2.3/1]

Contenitori associativi

  • [multi]{set,map}: tutti gli iteratori e riferimenti non interessati [23.1.2 / 8]

Adattatori per container

  • stack: ereditato dal contenitore sottostante
  • queue: ereditato dal contenitore sottostante
  • priority_queue: ereditato dal contenitore sottostante

cancellatura

Contenitori di sequenza

  • vector: ogni iteratore e riferimento dopo il punto di cancellazione sono invalidati [23.2.4.3/3]
  • deque: tutti gli iteratori e i riferimenti sono invalidati, a meno che i membri cancellati si trovino alla fine (fronte o retro) del deque (nel qual caso vengono invalidati solo gli iteratori e i riferimenti ai membri cancellati) [23.2.1.3/4]
  • list: solo gli iteratori e i riferimenti all'elemento cancellato sono invalidati [23.2.2.3/3]

Contenitori associativi

  • [multi]{set,map}: solo gli iteratori e i riferimenti agli elementi cancellati sono invalidati [23.1.2 / 8]

Adattatori per container

  • stack: ereditato dal contenitore sottostante
  • queue: ereditato dal contenitore sottostante
  • priority_queue: ereditato dal contenitore sottostante

Ridimensionamento

  • vector: come da inserire / cancellare [23.2.4.2/6]
  • deque: come da inserire / cancellare [23.2.1.2/1]
  • list: come da inserire / cancellare [23.2.2.2/1]

Nota 1

Se non diversamente specificato (esplicitamente o definendo una funzione in termini di altre funzioni), invocare una funzione membro del contenitore o passare un contenitore come argomento a una funzione di libreria non deve invalidare gli iteratori o modificare i valori degli oggetti all'interno di quel contenitore . [23.1 / 11]

Nota 2

Non è chiaro in C ++ 2003 se gli iteratori "end" sono soggetti alle regole di cui sopra ; dovresti supporre, comunque, che lo siano (come nella pratica questo è il caso).

Nota 3

Le regole per invalidare i puntatori sono le stesse come regole per invalidare i riferimenti.


5
Buona idea, solo per notare: penso che i contenitori associativi potrebbero essere piegati insieme in una sola riga, e potrebbe valere la pena aggiungere un'altra linea di quelli associativi non ordinati ... anche se non sono sicuro di come potrebbe essere la parte di rimodellamento mappato su insert / erase, conosci un modo per verificare se un rehash verrà attivato o no?
Matthieu M.,

1
IIRC, da qualche parte la specifica dice che l'iteratore finale non è un iteratore "per gli oggetti all'interno di quel contenitore". Mi chiedo come queste garanzie cercano l'iteratore finale in ogni caso?
Johannes Schaub - litb

1
@MuhammadAnnaqeeb: questa risposta, certamente, non chiarisce, dato che ho preso una scorciatoia, ma l'intenzione è quella di dire che il ridimensionamento è l' inserzione / cancellazione, come se fosse necessaria una riallocazione, potresti considerare che è la stessa della cancellazione quindi reinserendo tutti gli elementi interessati. Quella sezione della risposta potrebbe sicuramente essere migliorata.
Razze di leggerezza in orbita,

1
@Yakk: Ma non lo fa; vedere il testo standard citato. Sembra che sia stato risolto in C ++ 11 però. :)
Razze di leggerezza in orbita,

1
@metamorphosis: deque memorizza i dati in blocchi non contigui. L'inserimento all'inizio o alla fine può allocare un nuovo blocco, ma non si sposta mai attorno agli elementi precedenti, quindi i puntatori rimangono validi. Ma le regole per passare all'elemento successivo / precedente cambiano se viene allocato un nuovo blocco, quindi gli iteratori vengono invalidati.
Nick Matteo,

357

C ++ 11 (Fonte: regole di invalidamento Iterator (C ++ 0x) )


Inserimento

Contenitori di sequenza

  • vector: tutti gli iteratori e i riferimenti prima del punto di inserimento non sono interessati, a meno che la dimensione del nuovo contenitore sia maggiore della capacità precedente (nel qual caso tutti gli iteratori e riferimenti sono invalidati) [23.3.6.5/1]
  • deque: tutti gli iteratori e i riferimenti sono invalidati, a meno che l'elemento inserito non si trovi alla fine (fronte o retro) del deque (nel qual caso tutti gli iteratori sono invalidati, ma i riferimenti agli elementi non sono interessati) [23.3.3.4/1]
  • list: tutti gli iteratori e riferimenti non interessati [23.3.5.4/1]
  • forward_list: tutti gli iteratori e riferimenti non interessati (si applica a insert_after) [23.3.4.5/1]
  • array: (n / a)

Contenitori associativi

  • [multi]{set,map}: tutti gli iteratori e riferimenti non interessati [23.2.4 / 9]

Contenitori associativi non ordinati

  • unordered_[multi]{set,map}: tutti gli iteratori sono invalidati quando si verifica il rimescolamento, ma riferimenti non interessati [23.2.5 / 8]. Il reinserimento non si verifica se l'inserimento non causa il superamento delle dimensioni del contenitore z * Bdove si ztrova il fattore di carico massimo e Bil numero corrente di bucket. [23.2.5 / 14]

Adattatori per container

  • stack: ereditato dal contenitore sottostante
  • queue: ereditato dal contenitore sottostante
  • priority_queue: ereditato dal contenitore sottostante

cancellatura

Contenitori di sequenza

  • vector: ogni iteratore e riferimento al o dopo il punto di cancellazione sono invalidati [23.3.6.5/3]
  • deque: la cancellazione dell'ultimo elemento invalida solo gli iteratori e i riferimenti agli elementi cancellati e all'iteratore end-the-end; la cancellazione del primo elemento invalida solo gli iteratori e i riferimenti agli elementi cancellati; la cancellazione di qualsiasi altro elemento invalida tutti gli iteratori e riferimenti (incluso l'iteratore passato) [23.3.3.4/4]
  • list: solo gli iteratori e i riferimenti all'elemento cancellato sono invalidati [23.3.5.4/3]
  • forward_list: solo gli iteratori e i riferimenti all'elemento cancellato sono invalidati (vale per erase_after) [23.3.4.5/1]
  • array: (n / a)

Contenitori associativi

  • [multi]{set,map}: solo gli iteratori e i riferimenti agli elementi cancellati sono invalidati [23.2.4 / 9]

Contenitori associativi non ordinati

  • unordered_[multi]{set,map}: solo gli iteratori e i riferimenti agli elementi cancellati sono invalidati [23.2.5 / 13]

Adattatori per container

  • stack: ereditato dal contenitore sottostante
  • queue: ereditato dal contenitore sottostante
  • priority_queue: ereditato dal contenitore sottostante

Ridimensionamento

  • vector: come da inserire / cancellare [23.3.6.5/12]
  • deque: come da inserire / cancellare [23.3.3.3/3]
  • list: come da inserire / cancellare [23.3.5.3/1]
  • forward_list: come da inserire / cancellare [23.3.4.5/25]
  • array: (n / A)

Nota 1

Se non diversamente specificato (esplicitamente o definendo una funzione in termini di altre funzioni), invocare una funzione membro del contenitore o passare un contenitore come argomento a una funzione di libreria non deve invalidare gli iteratori o modificare i valori degli oggetti all'interno di quel contenitore . [23.2.1 / 11]

Nota 2

nessuna funzione swap () invalida riferimenti, puntatori o iteratori che si riferiscono agli elementi dei contenitori che vengono scambiati. [Nota: l'iteratore end () non fa riferimento a nessun elemento, quindi potrebbe essere invalidato . —End note] [23.2.1 / 10]

Nota 3

A parte le avvertenze di cui sopra swap(), non è chiaro se gli iteratori "finali" siano soggetti alle regole per contenitore sopra elencate ; dovresti supporre, comunque, che lo siano.

Nota 4

vectore tutti i contenitori associativi non ordinati supportano il reserve(n)che garantisce che non si verifichino ridimensionamenti automatici almeno fino a quando la dimensione del contenitore non aumenta n. Bisogna fare attenzione con i contenitori associativi non ordinati perché una futura proposta consentirà la specifica di un fattore di carico minimo, che consentirebbe di ricominciare insertdopo che un numero sufficiente di eraseoperazioni riduce le dimensioni del contenitore al di sotto del minimo; la garanzia deve essere considerata potenzialmente nulla dopo un erase.


Inoltre swap(), quali sono le regole per la validità dell'iteratore al momento dell'assegnazione di copia / spostamento?
arrivederci

@LightnessRacesinOrbit: come l'inserimento, la cancellazione, il ridimensionamento e lo scambio, l'assegnazione di copia / spostamento sono anche funzioni membro di std :: vector, quindi penso che potresti fornire anche a loro le regole di validità dell'iteratore.
arrivederci

@goodbyeera: intendi copiare / spostare assegnando un elemento? Ciò non influirà su alcun iteratore. Perché dovrebbe? Stai colpendo la nota 1 sopra.
Corse di leggerezza in orbita

1
Penso di aver fatto un errore, perché std::basic_stringnon sembra essere conteggiato come un contenitore e certamente non un contenitore nella sezione dello standard a cui si applica la nota. Tuttavia, dove si dice che SSO non è consentito (so che COW è)?
Deduplicatore,

2
Queste regole sono tutte uguali in C ++ 14? C ++ 17 (per quanto è ora noto)?
einpoklum,

40

E 'probabilmente la pena di aggiungere che un iteratore di inserimento di qualsiasi tipo ( std::back_insert_iterator, std::front_insert_iterator, std::insert_iterator) è garantito a rimanere valido fino a quando tutte le inserzioni vengono eseguite attraverso questo iteratore e si verifica nessun altro evento iteratore-invalidanti indipendente.

Ad esempio, quando si eseguono una serie di operazioni di inserimento in una std::vectorutilizzando std::insert_iterator, è del tutto possibile che questi inserimenti attiveranno la riallocazione del vettore, che invaliderà tutti gli iteratori che "puntano" in quel vettore. Tuttavia, si garantisce che l'iteratore di inserimento in questione rimanga valido, ovvero è possibile continuare in sicurezza la sequenza di inserimenti. Non è necessario preoccuparsi di innescare la riallocazione dei vettori.

Questo, ancora una volta, si applica solo agli inserimenti eseguiti tramite lo stesso iteratore di inserimento. Se l'evento invalidante dell'iteratore viene attivato da un'azione indipendente sul contenitore, anche l'inserimento dell'iteratore viene invalidato in conformità con le regole generali.

Ad esempio, questo codice

std::vector<int> v(10);
std::vector<int>::iterator it = v.begin() + 5;
std::insert_iterator<std::vector<int> > it_ins(v, it);

for (unsigned n = 20; n > 0; --n)
  *it_ins++ = rand();

è garantito per eseguire una valida sequenza di inserimenti nel vettore, anche se il vettore "decide" di riallocare da qualche parte nel mezzo di questo processo. Iteratore itdiventerà ovviamente non valido, ma it_inscontinuerà a rimanere valido.


22

Dal momento che questa domanda genera così tanti voti e che in un certo senso diventa una FAQ, immagino che sarebbe meglio scrivere una risposta separata per menzionare una differenza significativa tra C ++ 03 e C ++ 11 per quanto riguarda l'impatto std::vectordell'operazione di inserimento sul validità di iteratori e riferimenti rispetto a reserve()e capacity(), che la risposta più votata non ha riscontrato.

C ++ 03:

La riallocazione invalida tutti i riferimenti, i puntatori e gli iteratori che fanno riferimento agli elementi nella sequenza. È garantito che durante gli inserimenti che si verificano dopo una chiamata a reserve () non si verifica alcuna riallocazione fino al momento in cui un inserimento renderebbe la dimensione del vettore maggiore della dimensione specificata nella chiamata a riservare più recente () .

C ++ 11:

La riallocazione invalida tutti i riferimenti, i puntatori e gli iteratori che fanno riferimento agli elementi nella sequenza. È garantito che durante gli inserimenti non si verifica alcuna riallocazione dopo una chiamata a reserve () fino al momento in cui un inserimento renderebbe la dimensione del vettore maggiore del valore di capacity () .

Quindi in C ++ 03 non è " unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)" come indicato nell'altra risposta, invece dovrebbe essere " greater than the size specified in the most recent call to reserve()". Questa è una cosa che C ++ 03 differisce da C ++ 11. In C ++ 03, una volta che insert()fa sì che la dimensione del vettore raggiunga il valore specificato nella reserve()chiamata precedente (che potrebbe essere più piccola della corrente capacity()poiché reserve()potrebbe risultare più grande di capacity()quanto richiesto), qualsiasi successiva insert()potrebbe causare riallocazione e invalidare tutti gli iteratori e riferimenti. In C ++ 11, ciò non accadrà e puoi sempre fidarti capacity()di sapere con certezza che la prossima riallocazione non avrà luogo prima che la dimensione superi capacity().

In conclusione, se stai lavorando con un vettore C ++ 03 e vuoi assicurarti che non si verifichi una riallocazione quando esegui l'inserimento, è il valore dell'argomento che hai passato in precedenza reserve()che dovresti controllare la dimensione, non il valore di ritorno di una chiamata a capacity(), altrimenti potresti rimanere sorpreso da una riallocazione " prematura ".


14
Tuttavia, sparerei a qualsiasi compilatore che mi avesse fatto questo e nessuna giuria del paese mi avrebbe condannato.
Yakk - Adam Nevraumont,

9
Non ho "mancato di notare" questo; è stato un errore editoriale in C ++ 03 che è stato corretto in C ++ 11. Nessun compilatore tradizionale sfrutta l'errore.
Corse della leggerezza in orbita,

1
@Yakk Penso che gcc invalidi già gli iteratori in tali situazioni.
ShreevatsaR,

2

Ecco una bella tabella riassuntiva da cppreference.com :

inserisci qui la descrizione dell'immagine

Qui, l' inserimento si riferisce a qualsiasi metodo che aggiunge uno o più elementi al contenitore e la cancellazione si riferisce a qualsiasi metodo che rimuove uno o più elementi dal contenitore.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.