Com o C ++ 17 , shared_ptrpode ser usado para gerenciar uma matriz alocada dinamicamente. O shared_ptrargumento 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[] pquando Té um tipo de matriz ou delete pquando Tnã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[] pseja 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_typeagora é 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 Tnã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_ptrdeletenew[]delete[]delete
Para usar corretamente shared_ptrcom 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_ptrchamará corretamente delete[]ao destruir o objeto gerenciado.
O deleter personalizado acima pode ser substituído por
a std::default_deleteespecializaçã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_ptrpara permitir que ela funcione imediatamente para os casos em que possui uma matriz de objetos. O rascunho atual das shared_ptralterações previstas para este TS pode ser encontrado na N4082 . Essas alterações serão acessíveis através do std::experimentalnamespace e incluídas no <experimental/memory>cabeçalho. Algumas das alterações relevantes para dar suporte shared_ptra matrizes são:
- A definição do tipo de membro é element_typealterada
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_ptrespecializaçã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 : Ydeve ser do tipo completo. A expressão delete[] pquando Té um tipo de matriz ou delete p, quando Tnã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.