2012-02-19 12 views
5

Considerare un iteratore standard in cui è necessario allocare memoria per attraversare una struttura dati. Lo standard consente a un iteratore di generare un'eccezione se la memoria non può essere allocata? Ad esempio, pensa a un iteratore di input per strutture di dati ad albero. In questo caso, per attraversare l'albero devi aggiungere e mantenere un puntatore al genitore di ciascun nodo (il che rallenterebbe le operazioni che non richiedono un tale puntatore, come per inserire/cancella/trova nell'albero) o usare uno stack per aiutare l'iteratore a memorizzare i puntatori ai nodi attraversati. In questo caso, mentre avanza lo stack potrebbe crescere fino a quando non c'è più memoria libera e l'iteratore è costretto a lanciare.Sono consentite le operazioni di iteratore standard da lanciare?

+0

"In questo caso, per attraversare l'albero devi aggiungere e mantenere un puntatore al genitore di ciascun nodo" Ogni nodo * dovrebbe * avere un puntatore al suo genitore. Altrimenti è un albero "in avanti", dove puoi solo andare giù. Direi che un iteratore che utilizzava uno stack sarebbe stato interrotto sia per fare affidamento su un oggetto globale o condiviso (rendendolo quindi non thread-safe) sia per allocare memoria solo per attraversare l'albero. Si noti che gli iteratori per 'std :: forward_list' in C++ 11 sono iteratori forward; tu * non puoi * tornare indietro. –

+1

@Nicol Chi ha detto che lo stack sarebbe globale o condiviso? Lo stack è associato all'istanza iteratore. Inoltre, gli stack sono probabilmente l'unico modo per implementare * gli iteratori di input * sugli alberi in cui i nodi hanno solo puntatori ai loro successori. – Martin

+0

Gli iteratori di input non * inseriscono * elementi nella struttura dati. Possono solo leggere e modificare elementi già esistenti. Gli iteratori di output possono, ma noterete che molti di questi sono adattatori iteratori per * container *, non iteratori. E i nodi degli alberi dovrebbero indicare i loro genitori. –

risposta

5

Sì, è possibile lanciare un metodo iteratore in C++ e, come indicato, può verificarsi in determinate circostanze.

L'unica classe di funzioni in C++ che non può essere lanciata è un distruttore. E questo è solo per convenzione (perché rende alcune operazioni quasi impossibili da eseguire correttamente). I distruttori possono lanciare, è solo molto brutto lasciarglielo fare.

Le singole funzioni possono essere contrassegnate con throw() per impedire che vengano lanciate.

+0

"L'unica funzione in C++ che non può essere lanciata è un distruttore." Non vero. Lo standard definisce alcune funzioni della libreria standard che non è consentito lanciare. Ad esempio, la maggior parte dei costruttori di 'auto_ptr' sono designati' throw() 'in C++ 03, il che significa che non possono lanciare. In C++ 11, quasi ogni implementazione di 'swap' è definita con' noexcept'. –

+0

@NicolBolas Stavo tentando in più di fare una dichiarazione generale sull'opportunità o meno di lanciare una classe/tipo di funzione. Il modificatore 'throw()' dice certamente che una singola funzione non può essere lanciata. Aggiungerò comunque una nota a riguardo. Non ho familiarità con 'noexcept', hai una buona pagina di riferimento per questo. – JaredPar

+0

@JaredPar: è la nuova sintassi introdotta in C++ 11. Quale Visual C++ ha finora ignorato, anche se dovrebbe essere una delle cose più facili da implementare (quasi identico a 'throw()' + un tipo di tratto). Vedere la sezione 15.4 e 5.3.7 della norma C++ 11. –

Problemi correlati