A regra de 5 é uma extensão válida da regra de 3 ou implica uma otimização prematura?

5

Estou familiarizado com a noção em c ++ da regra de 3 , no entanto, desde o lançamento do C ++ 11 eu vi algumas fontes sugerindo que deveria ser estendido para uma "regra de 5", ou seja, o construtor de movimento e o operador de atribuição de movimento também devem ser implementados sempre que os outros estiverem. Qual é a lógica por trás de tal regra? Meu entendimento é que na maioria dos casos a implementação da semântica de movimento é necessária apenas como uma otimização - estou errado sobre isso, ou a chamada regra de cinco sobre otimizar meu código (e, portanto, substancialmente menos importante que a regra de 3 , que é sobre como evitar armadilhas que podem levar a comportamentos inesperados)?

    
por Jules 25.12.2014 / 22:03
fonte

2 respostas

5

As semânticas de movimento foram adicionadas ao C ++ 11 de tal forma que a "regra de 3" ainda é válida e suficiente para evitar as armadilhas que se pretende evitar (embora haja melhores maneiras na maioria das situações "rule of 0" ).
Também não há armadilhas adicionais adicionadas à linguagem que a "regra de 5" ajudaria a evitar. Nesse sentido, a regra de 5 é mais sobre otimização do que sobre evitar armadilhas.

Por outro lado, tratar a "regra de 5" como uma extensão para a "regra de 3" ajuda você a lembrar que em C ++ 11 existem duas funções de membros especiais adicionais que você precisa considerar quando sua classe faz algo especial que precisa de um destrutor ou um construtor de cópias.

E embora a semântica de movimento seja uma otimização, fornecer um operador de movimento e / ou atribuição de movimento não significa que você está otimizando prematuramente , assim como selecionar o algoritmo correto não é prematuro otimização.
Adicionar suporte para mover a semântica para sua classe, quando faz sentido, geralmente exige pouco esforço e não diminui a legibilidade / manutenção do código.

    
por 26.12.2014 / 11:52
fonte
5

A Regra dos Cinco é ex-idiomática. Foi apenas idiomática por um período muito breve antes da Regra do Zero.

O princípio da Regra de 3 tornou-se obsoleto ao escrever suas próprias classes de manipulação de recursos tornou-se obsoleto, que é quando seu compilador suporta referências de valor. Se você implementar em termos de unique_ptr, o que você pode para praticamente todos os recursos, porque o deleter é tão personalizável, você só precisa de uma atribuição de cópia personalizada e copiar construtor- assim dois. Se você precisar dar suporte à cópia. Não há razão para implementar seu próprio destruidor, mover o operador de atribuição ou mover o construtor na grande maioria dos casos.

A regra do código Três não é quebrada , mas é muito mais difícil de manter do que o código da regra zero e não é tão eficiente. As operações de movimentação oferecem correção em muitos casos, como unique_ptr , então você deve se esforçar para apoiá-las sempre que possível.

São operações de cópia que agora são em grande parte redundantes em face de movimentos, e não o contrário.

Em outras palavras, unique_ptr é tão flexível, e operações padronizadas são tão úteis, que quase não há mais motivo para implementar seus próprios membros especiais. Na verdade, não há praticamente nenhum motivo para implementar suas próprias classes de manipulação de recursos. E como essas classes praticamente nunca existem, não há razão para ter um idioma para construí-las.

    
por 26.12.2014 / 13:40
fonte