Com o C ++ 17 , shared_ptr
pode ser usado para gerenciar uma matriz alocada dinamicamente. O shared_ptr
argumento do modelo neste caso deve ser T[N]
ou T[]
. Então você pode escrever
shared_ptr<int[]> sp(new int[10]);
No n4659, [util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
Requer: Y
deve ser do tipo completo. A expressão delete[] p
quando T
é um tipo de matriz ou delete p
quando T
não é um tipo de matriz deve ter um comportamento bem definido e não deve gerar exceções.
...
Observações: Quando T
é um tipo de matriz, este construtor não devem participar na resolução de sobrecarga, a menos que a expressão delete[] p
seja bem formado e ou T
é U[N]
e Y(*)[N]
é convertível em T*
, ou T
é
U[]
e Y(*)[]
é convertível para T*
. ...
Para suportar isso, o tipo de membro element_type
agora é definido como
using element_type = remove_extent_t<T>;
Elementos da matriz podem ser acessados usando operator[]
element_type& operator[](ptrdiff_t i) const;
Exige: get() != 0 && i >= 0
. Se T
é U[N]
, i < N
. ...
Comentários: Quando T
não é um tipo de matriz, não é especificado se esta função de membro é declarada. Se for declarado, não é especificado qual é o seu tipo de retorno, exceto que a declaração (embora não necessariamente a definição) da função seja bem formada.
Antes do C ++ 17 , nãoshared_ptr
podia ser usado para gerenciar matrizes alocadas dinamicamente. Por padrão, chamará o objeto gerenciado quando não houver mais referências a ele. No entanto, quando você aloca usando, precisa chamar , e não , para liberar o recurso.shared_ptr
delete
new[]
delete[]
delete
Para usar corretamente shared_ptr
com uma matriz, você deve fornecer um deleter personalizado.
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
Crie o shared_ptr da seguinte maneira:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
Agora shared_ptr
chamará corretamente delete[]
ao destruir o objeto gerenciado.
O deleter personalizado acima pode ser substituído por
a std::default_delete
especialização parcial para tipos de matriz
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
uma expressão lambda
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
Além disso, a menos que você realmente precise compartilhar a participação do objeto gerenciado, a unique_ptr
é mais adequado para esta tarefa, pois possui uma especialização parcial para os tipos de matriz.
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
Alterações introduzidas pelas extensões C ++ para fundamentos de biblioteca
Outra alternativa pré-C ++ 17 às listadas acima foi fornecida pela Especificação Técnica dos Fundamentos da Biblioteca , que foi aprimorada shared_ptr
para permitir que ela funcione imediatamente para os casos em que possui uma matriz de objetos. O rascunho atual das shared_ptr
alterações previstas para este TS pode ser encontrado na N4082 . Essas alterações serão acessíveis através do std::experimental
namespace e incluídas no <experimental/memory>
cabeçalho. Algumas das alterações relevantes para dar suporte shared_ptr
a matrizes são:
- A definição do tipo de membro é element_type
alterada
typedef T element_type;
typedef typename remove_extent<T>::type element_type;
- Membro operator[]
está sendo adicionado
element_type& operator[](ptrdiff_t i) const noexcept;
- Diferentemente da unique_ptr
especialização parcial para matrizes, ambos shared_ptr<T[]>
e shared_ptr<T[N]>
serão válidos e ambos resultarão na delete[]
chamada na matriz gerenciada de objetos.
template<class Y> explicit shared_ptr(Y* p);
Requer : Y
deve ser do tipo completo. A expressão delete[] p
quando T
é um tipo de matriz ou delete p
, quando T
não é um tipo de matriz, deve ser bem formada, deve ter um comportamento bem definido e não deve gerar exceções. Quando T
é U[N]
, Y(*)[N]
deve ser conversível em T*
; Quando T
é U[]
, Y(*)[]
deve ser conversível em T*
; caso contrário, Y*
será convertível em T*
.
std::vector
. Você precisaria ter cuidado para passar a matriz usando referências para não fazer cópias dela. A sintaxe para acessar dados é mais limpa que shared_ptr, e redimensioná-la é muito, muito fácil. E você obtém toda a bondade do STL, se quiser.