Por que é errado usar std :: auto_ptr com contêineres padrão?

Por que é errado usar std::auto_ptr com contêineres padrão?

O C ++ Standard diz que um elemento STL deve ser “copy-constructible” e “assignable”. Em outras palavras, um elemento deve ser capaz de ser atribuído ou copiado e os dois elementos são logicamente independentes. std::auto_ptr não cumpre este requisito.

Tomemos por exemplo este código:

 class X { }; std::vector > vecX; vecX.push_back(new X); std::auto_ptr pX = vecX[0]; // vecX[0] is assigned NULL. 

Para superar essa limitação, você deve usar os pointers std::unique_ptr , std::shared_ptr ou std::weak_ptr ou os equivalentes de boost se você não tiver o C ++ 11. Aqui está a documentação da biblioteca de reforço para esses pointers inteligentes.

A semântica de cópia de auto_ptr não é compatível com os contêineres.

Especificamente, copiar um auto_ptr para outro não cria dois objects iguais, já que um deles perdeu a propriedade do ponteiro.

Mais especificamente, copiar um auto_ptr faz com que uma das cópias solte o ponteiro. Qual destes permanece no recipiente não está definido. Portanto, você pode perder aleatoriamente o access a pointers se você armazenar auto_ptrs nos contêineres.

Dois excelentes artigos sobre o assunto:

  • Ponteiros Inteligentes – O que, Por que, Qual?
  • Guru da Semana # 25

Os contêineres STL precisam ser capazes de copiar os itens armazenados neles e são projetados para esperar que o original e a cópia sejam equivalentes. Os objects de ponteiro automático têm um contrato completamente diferente, em que a cópia cria uma transferência de propriedade. Isso significa que os contêineres de auto_ptr exibirão um comportamento estranho, dependendo do uso.

Há uma descrição detalhada do que pode dar errado no item 8 do Effective STL (Scott Meyers) e também uma descrição não tão detalhada no item 13 do Effective C ++ (Scott Meyers).

Contêineres STL armazenam cópias de itens contidos. Quando um auto_ptr é copiado, ele define o antigo ptr como nulo. Muitos methods de contêiner são quebrados por esse comportamento.

O padrão C ++ 03 (ISO-IEC 14882-2003) diz na cláusula 20.4.5, parágrafo 3:

[…] [ Nota: auto_ptr não atende aos requisitos CopyConstructible e Assignable para elementos de contêiner da Biblioteca Padrão e, assim, instanciar um contêiner da Biblioteca Padrão com um auto_ptr resulta em um comportamento indefinido. – nota final

C ++ 11 Standard (ISO-IEC 14882-2011) diz no apêndice D.10.1, parágrafo 3:

[…] Observação: instâncias de auto_ptr atendem aos requisitos de MoveConstructible e MoveAssignable, mas não atendem aos requisitos de CopyConstructible e CopyAssignable. – nota final

C ++ 14 Standard (ISO-IEC 14882-2014) diz no apêndice C.4.2 Anexo D: características de compatibilidade:

Alteração : Os modelos de class auto_ptr, unary_function e binary_function, os modelos de function random_shuffle e os modelos de function (e seus tipos de retorno) ptr_fun, mem_fun, mem_fun_ref, bind1st e bind2nd não estão definidos.
Justificativa : Substituída por novos resources.
Efeito no recurso original : o código C ++ 2014 válido que usa esses modelos de class e modelos de function pode falhar na compilation deste padrão internacional.