Con C ++ 17 , shared_ptrpuò essere utilizzato per gestire un array allocato dinamicamente. L' shared_ptrargomento template in questo caso deve essere T[N]o T[]. Quindi puoi scrivere
shared_ptr<int[]> sp(new int[10]);
Da n4659, [util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Richiede: Y deve essere un tipo completo. L'espressione delete[] p, quando Tè un tipo di array o delete p, quando Tnon è un tipo di array, deve avere un comportamento ben definito e non deve generare eccezioni.
...
Note: Quando Tè un tipo di array, questo costruttore non deve partecipare alla risoluzione del sovraccarico a meno che l'espressione non delete[] psia ben formata e sia o Tsia U[N]ed Y(*)[N]è convertibile in T*, sia Tsia
U[]e Y(*)[]sia convertibile in T*. ...
Per supportare ciò, il tipo di membro element_typeè ora definito come
using element_type = remove_extent_t<T>;
È possibile accedere agli elementi dell'array utilizzando operator[]
element_type& operator[](ptrdiff_t i) const;
Richiede: get() != 0 && i >= 0 . Se Tè U[N], i < N. ...
Note: quando Tnon è un tipo di array, non è specificato se viene dichiarata questa funzione membro. Se viene dichiarato, non è specificato quale sia il suo tipo di ritorno, tranne che la dichiarazione (sebbene non necessariamente la definizione) della funzione deve essere ben formata.
Prima di C ++ 17 , nonshared_ptr poteva essere utilizzato per gestire array allocati dinamicamente. Per impostazione predefinita, chiamerà l'oggetto gestito quando non vi saranno più riferimenti. Tuttavia, quando si assegna l'utilizzo è necessario chiamare e non per liberare la risorsa.shared_ptrdeletenew[]delete[]delete
Per utilizzare correttamente shared_ptrun array, è necessario fornire un deleter personalizzato.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Creare shared_ptr come segue:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Ora shared_ptrchiamerà correttamente delete[]quando si distrugge l'oggetto gestito.
Il deleter personalizzato sopra può essere sostituito da
la std::default_deletespecializzazione parziale per i tipi di array
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
un'espressione lambda
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Inoltre, a meno che tu non abbia effettivamente bisogno di condividere la condivisione dell'oggetto gestito, a unique_ptrè più adatto per questa attività, poiché ha una specializzazione parziale per i tipi di array.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Modifiche introdotte dalle estensioni C ++ per i fondamenti della biblioteca
Un'altra alternativa pre-C ++ 17 a quelle sopra elencate è stata fornita dalla Specifica tecnica sui fondamenti della biblioteca , che è stata ampliata shared_ptrper consentirgli di lavorare fuori dagli schemi per i casi in cui possiede una serie di oggetti. La bozza attuale delle shared_ptrmodifiche previste per questo TS è disponibile in N4082 . Queste modifiche saranno accessibili tramite lo std::experimentalspazio dei nomi e incluse <experimental/memory>nell'intestazione. Alcune delle modifiche rilevanti a supporto shared_ptrdegli array sono:
- La definizione del tipo di membro element_typecambia
typedef T element_type;
typedef typename remove_extent<T>::type element_type;
- Il membro operator[]è stato aggiunto
element_type& operator[](ptrdiff_t i) const noexcept;
- A differenza della unique_ptrspecializzazione parziale per gli array, entrambi shared_ptr<T[]>e shared_ptr<T[N]>saranno validi ed entrambi risulteranno delete[]chiamati sull'array di oggetti gestito.
template<class Y> explicit shared_ptr(Y* p);
Richiede : Ydeve essere un tipo completo. L'espressione delete[] p, quando Tè un tipo di array, o delete p, quando Tnon è un tipo di array, deve essere ben formata, deve avere un comportamento ben definito e non deve generare eccezioni. Quando Tè U[N], Y(*)[N]deve essere convertibile in T*; quando Tè U[], Y(*)[]deve essere convertibile in T*; in caso contrario, Y*sarà convertibile in T*.
std::vector. Dovresti fare attenzione a passare l'array in giro usando i riferimenti in modo da non farne copie. La sintassi per l'accesso ai dati è più pulita di shared_ptr e il ridimensionamento è molto semplice. E ottieni tutta la bontà STL se mai lo desideri.