Domanda

La progettazione di un nuovo sistema da zero.Sarò con il STL per memorizzare elenchi e mappe di certo a lungo gli oggetti live.

Domanda:Devo essere sicuro che i miei oggetti sono costruttori di copia e archiviare le copie di oggetti all'interno della mia contenitori STL, o è generalmente migliore per gestire la vita & ambito di me stesso e basta memorizzare i puntatori a tali oggetti nel mio contenitori STL?

Mi rendo conto che questo è un po ' corto sui dettagli, ma sto cercando il "teorico" migliore risposta, se esiste, dal momento che so che entrambe queste soluzioni sono possibili.

Due molto evidente svantaggio di giocare con i puntatori:1) devo gestire l'allocazione/deallocazione di questi oggetti a me stesso in un ambito al di là del STL.2) non riesco a creare un temp oggetto in pila e aggiungere al mio contenitori.

C'è qualcos'altro che mi sto perdendo?

È stato utile?

Soluzione

Dato che le persone stanno intervenendo sull'efficacia dell'uso dei puntatori.

Se stai pensando di utilizzare uno std :: vector e se gli aggiornamenti sono pochi e spesso esegui l'iterazione della tua raccolta ed è un tipo non polimorfico che memorizza un oggetto " copia " sarà più efficace poiché otterrai una migliore località di riferimento.

Otoh, se gli aggiornamenti sono comuni, i puntatori di memorizzazione salveranno i costi di copia / trasferimento.

Altri suggerimenti

Questo dipende davvero dalla tua situazione.

Se i tuoi oggetti sono piccoli e fare una copia dell'oggetto è leggero, la memorizzazione dei dati all'interno di un contenitore stl è semplice e facile da gestire secondo me perché non devi preoccuparti della gestione della vita.

Se gli oggetti sono di grandi dimensioni e avere un costruttore predefinito non ha senso o se le copie degli oggetti sono costose, probabilmente la memorizzazione con i puntatori è la strada da percorrere.

Se decidi di utilizzare i puntatori agli oggetti, dai un'occhiata a Boost Pointer Container Library . Questa libreria boost avvolge tutti i contenitori STL per l'uso con oggetti allocati dinamicamente.

Ogni contenitore puntatore (ad esempio ptr_vector) diventa proprietario di un oggetto quando viene aggiunto al contenitore e gestisce per te la durata di tali oggetti. Puoi anche accedere a tutti gli elementi in un contenitore ptr_ per riferimento. Questo ti consente di fare cose come

class BigExpensive { ... }

// create a pointer vector
ptr_vector<BigExpensive> bigVector;
bigVector.push_back( new BigExpensive( "Lexus", 57700 ) );
bigVector.push_back( new BigExpensive( "House", 15000000 );

// get a reference to the first element
MyClass& expensiveItem = bigList[0];
expensiveItem.sell();

Queste classi avvolgono i contenitori STL e funzionano con tutti gli algoritmi STL, il che è davvero utile.

Esistono anche funzioni per trasferire la proprietà di un puntatore nel contenitore al chiamante (tramite la funzione di rilascio nella maggior parte dei contenitori).

Se si memorizza polymporhic oggetti è sempre necessario utilizzare un insieme di puntatori di classe base.

Se si prevede di non utilizzare diversi tipi derivati nella vostra collezione, è necessario memorizzare i puntatori o di avere mangiato con il taglio demone.

Mi spiace saltare tra 3 anni dopo l'evento, ma una nota di avvertimento qui ...

Nel mio ultimo grande progetto, la mia struttura di dati centrale era un insieme di oggetti abbastanza semplici. Circa un anno dopo l'inizio del progetto, quando i requisiti si sono evoluti, mi sono reso conto che l'oggetto doveva effettivamente essere polimorfico. Ci sono volute alcune settimane di chirurgia cerebrale difficile e sgradevole per sistemare la struttura dei dati come un insieme di puntatori di classe base e per gestire tutto il danno collaterale nella conservazione degli oggetti, nel lancio e così via. Mi ci sono voluti un paio di mesi per convincermi che il nuovo codice stava funzionando. Per inciso, questo mi ha fatto riflettere intensamente su quanto sia ben progettato il modello a oggetti di C ++.

Nel mio attuale grande progetto, la mia struttura di dati centrale è un insieme di oggetti abbastanza semplici. Circa un anno dopo l'inizio del progetto (che sembra essere oggi), mi sono reso conto che l'oggetto in realtà deve essere polimorfico. Torna alla rete, ha trovato questo thread e ha trovato il link di Nick alla libreria contenitore puntatore Boost. Questo è esattamente ciò che ho dovuto scrivere l'ultima volta per sistemare tutto, quindi questa volta ci proverò.

La morale, per me, comunque: se le tue specifiche non sono espresse al 100% in pietra, cerca suggerimenti e potresti potenzialmente risparmiare molto lavoro in seguito.

Perché non ottenere il meglio da entrambi i mondi: crea un contenitore di puntatori intelligenti (come boost::shared_ptr o std::shared_ptr ). Non è necessario gestire la memoria e non è necessario gestire operazioni di copia di grandi dimensioni.

Generalmente archiviare gli oggetti direttamente nel contenitore STL è la cosa migliore in quanto è più semplice, più efficiente ed è più semplice per usare l'oggetto.

Se l'oggetto stesso ha una sintassi non copiabile o è un tipo di base astratto, sarà necessario memorizzare i puntatori (è più semplice usare shared_ptr)

Sembra che tu abbia una buona comprensione della differenza. Se gli oggetti sono piccoli e facili da copiare, allora memorizzali.

In caso contrario, penserei di archiviare i puntatori intelligenti (non auto_ptr, un riferimento che conta i puntatori intelligenti) in quelli allocati nell'heap. Ovviamente, se si opta per puntatori intelligenti, non è possibile memorizzare oggetti allocati nello stack temporaneo (come si è detto).

@ Torbj & # 246; rn ha un buon punto sull'affettare.

L'uso dei puntatori sarà più efficiente poiché i contenitori copieranno solo i puntatori anziché gli oggetti completi.

Ci sono alcune informazioni utili qui sui contenitori STL e sui puntatori intelligenti:

Perché è sbagliato usare std :: auto_ptr lt &; > con contenitori standard?

Se si desidera fare riferimento agli oggetti altrove nel codice, archiviare un vettore di boost :: shared_ptr. Ciò garantisce che i puntatori all'oggetto rimarranno validi se si ridimensiona il vettore.

Ie:

std::vector<boost::shared_ptr<protocol> > protocols;
...
connection c(protocols[0].get()); // pointer to protocol stays valid even if resized

Se nessun altro memorizza i puntatori agli oggetti o l'elenco non si ingrandisce e si restringe, è sufficiente archiviarlo come oggetti semplici:

std::vector<protocol> protocols;
connection c(protocols[0]); // value-semantics, takes a copy of the protocol

Questa domanda mi ha infastidito per un po '.

Mi appoggio alla memorizzazione dei puntatori, ma ho alcuni requisiti aggiuntivi (wrapper lua SWIG) che potrebbero non essere applicabili a te.

Il punto più importante in questo post è testarlo tu , usando i tuoi oggetti

L'ho fatto oggi per testare la velocità di chiamata di una funzione membro su una raccolta di 10 milioni di oggetti, 500 volte.

La funzione aggiorna xey in base a xdir e ydir (tutte le variabili dei membri float).

Ho usato un elenco std :: per contenere entrambi i tipi di oggetti e ho scoperto che la memorizzazione dell'oggetto nell'elenco è leggermente più veloce rispetto all'uso di un puntatore. D'altra parte, le prestazioni sono state molto vicine, quindi dipende da come verranno utilizzate nella tua applicazione.

Per riferimento, con -O3 sul mio hardware i puntatori hanno impiegato 41 secondi per essere completati e gli oggetti grezzi hanno impiegato 30 secondi per essere completati.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top