Per creare un oggetto B
in uno stato valido non è necessario eseguire altre operazioni. Non è nemmeno necessario dichiarare e implementare il costruttore e il distruttore per B
. std::vector<std::shared_ptr<A>>
che è un membro di B
verrà inizializzato di default nel costruttore B
, il che significa che non avrà ancora elementi in un contenitore. Sarà anche correttamente cancellato in ~B
grazie a std::vector
e std::shared_ptr
distruttori.
D'altra parte se per esempio si desidera inizializzarlo in qualche modo (ad es.3 valori) è possibile utilizzare il costruttore std::initializer_list
di std::initializer_list
nell'elenco di inizializzazione del costruttore di B
. Per esempio:
class B
{
public:
B(): _innerArray{ std::make_shared<A>(),
std::make_shared<A>(),
std::make_shared<A>() } {}
~B() {}
private:
std::vector<std::shared_ptr<A>> _innerArray;
};
Ricordate che std::make_shared
utilizza l'inoltro in modo perfetto si passa A
argomenti 's costruttore come gli argomenti della funzione e non l'oggetto classe stessa.
Rispondere alle vostre preoccupazioni sul design Vorrei incoraggiarvi a pensare prima alla proprietà esclusiva dei membri di un vettore prima di decidere di condividerli.
Sopra l'implementazione è più efficace per molti motivi. Prima di tutto rende più chiaro il tuo progetto su chi è responsabile per la durata di A
s. Avanti std::unique_ptr
è più veloce perché non richiede il conteggio dei riferimenti sicuro. E, ultimo ma non meno importante, non costa alcuna memoria aggiuntiva (rispetto al normale puntatore C) mentre lo std::shared_ptr
può richiedere decine di byte (24-48) per memorizzare dati di stato condivisi che sono altamente inefficaci quando si opera su classi piccole. Questo è il motivo per cui io uso sempre std::unique_ptr
come il mio primo puntatore intelligente e faccio solo un ripiego a std::shared_ptr
quando è davvero necessario.
EDIT:
Rispondere tua modifica vorrei creare 3 contenitori di classi A
, B
, C
. A seconda del fatto se avete bisogno loro di essere polimorfico o no avrei memorizzare sia i valori del genere (di tipo non polimorfici):
std::deque<A> as;
std::deque<B> bs;
std::deque<C> cs;
o (tipi polimorfi):
std::vector<std::unique_ptr<A>> as;
std::vector<std::unique_ptr<B>> bs;
std::vector<std::unique_ptr<C>> cs;
in questo ordine (as
devono vivere più a lungo di bs
e bs
devono vivere più a lungo di cs
). Quindi avrei solo std::vector<A*>
all'interno della classe B
e std::vector<B*>
all'interno della classe C
senza alcun utilizzo intelligente di puntatori.
Spero che questo aiuti.
EDIT:
Modificato std::vector
al std::deque
nel primo caso che permette riferimenti/puntatori ad elementi contenitori sopravvivono contenitori estensioni con push_back()
. Tuttavia non sopravviveranno cancellando elementi, ordinamento o altre cose.
Controllo di integrità: è necessario il puntatore qui? E se sì, dovrebbe essere un puntatore condiviso? –
Si suppone che la classe B abbia accesso ma non possiede alcuni oggetti memorizzati altrove. Non vedo l'uso di unique_ptr invece di shared_ptr che ha alcun senso qui, ma sono un noob ai puntatori intelligenti. –
@Pavel Hai ragione: il tuo scenario preclude l'uso di 'unique_ptr' e richiede l'uso di puntatori. Tuttavia, se non si presume che 'B' diventi proprietario, prenderei in considerazione l'utilizzo di puntatori raw invece di puntatori condivisi. Dopotutto, questi ultimi denotano * proprietà condivisa * (ma forse è ciò che si richiede dopo tutto). –