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?
risposta
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.
"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'. –
@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
@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. –
- 1. Sono consentite le grammatiche boost-spirit ricorsive?
- 2. Perché le virgolette doppie e le barre retroverse non sono consentite nelle stringhe nello standard JSON?
- 3. Le transazioni nidificate sono consentite in MySQL?
- 4. Qual è l'eccezione standard da lanciare in Java per operazioni non supportate/implementate?
- 5. Dove sono consentite le interruzioni di riga nelle espressioni Haskell?
- 6. Perché le colonne della tabella di stile non sono consentite?
- 7. Funzione stimata tabella remota Le chiamate non sono consentite
- 8. Le operazioni logiche su più operazioni modulo sono ottimizzate?
- 9. ORA-30483: le funzioni della finestra non sono consentite qui
- 10. Perché le interfacce non sono consentite come membri delle annotazioni?
- 11. PCRE: le backferger non sono consentite nei lookbehinds?
- 12. Quali sono le eccezioni standard di Scala?
- 13. Quali sono le monadi Scala standard diverse da Opzione?
- 14. Esiste un iteratore ciclico standard C++
- 15. Le operazioni in virgola mobile sono associate in C?
- 16. Le macro Variadic non sono standard?
- 17. Le definizioni di macro vuote sono consentite in C? Come si comportano?
- 18. Le operazioni di stringa .NET sono sensibili al maiuscolo/minuscolo?
- 19. Quali unità sono consentite in google.maps.Size?
- 20. Quale eccezione da lanciare quando le lunghezze delle sequenze non sono le stesse
- 21. Le operazioni rsync sono atomiche a livello di file?
- 22. BitSet mutabile Scala, dove sono le operazioni di muting?
- 23. Le query di MongoDB sono operazioni lato client?
- 24. Le operazioni da atomic.h sembrano non atomiche
- 25. Quale tipo di eccezione da lanciare per le stringhe
- 26. Memcached - Le operazioni GET e SET sono atomiche?
- 27. Perché non sono consentite le variabili di indice OpenMP non firmate?
- 28. Le espressioni sono consentite solo come primo elemento di una pipeline
- 29. numpy.memmap da operazioni numpy
- 30. Quali sono le operazioni banali in std :: is_trivially_copy_constructible in C++
"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. –
@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
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. –