cppreference define "Construtor de movimento trivial":
O construtor de movimento para a classe T é trivial se todas as condições a seguir forem verdadeiras:
NÃO é fornecido pelo usuário (ou seja, é definido implicitamente ou padrão);
T não possui funções de membro virtual;T não possui classes básicas virtuais;
o construtor de movimento selecionado para cada base direta de T é trivial;
o construtor move selecionado para cada tipo de classe não estática (ou matriz de tipo de classe) membro de T é trivial.
cppreference também define "construtor de movimento definido implicitamente":
Se o construtor de movimento declarado implicitamente NEM for excluído NEM trivial, ele será definido (isto é, um corpo de função será gerado e compilado) pelo compilador se odr for usado ou necessário para avaliação constante.
O construtor de movimento declarado implicitamente NÃO deve ser excluído é óbvio. Mas "não deve ser trivial" soa confuso para mim.
Isso não significa que, se NÃO for trivial, deve ser "fornecido pelo usuário"? E se já é "um fornecido pelo usuário", então por que "um declarado implicitamente" entra em ação?
Então, o que há de errado aqui? Qual é o objetivo de um construtor de movimento declarado implicitamente NÃO ser trivial? Por favor ajude.
Não. Se o construtor for fornecido pelo usuário, não pode ser trivial. Mas não ser trivial não significa que não possa ser declarado implicitamente.
Não tenho certeza do que você quer dizer com isso. Um construtor de movimentação é fornecido pelo usuário ou declarado implicitamente. Se for declarado implicitamente, pode ser trivial (se atender a mais critérios).
Compare essas duas classes:
A
tem construtor de movimento definido implicitamente e trivial.B
tem construtor de movimento declarado implicitamente, mas não trivial (porquestd::string
tem construtor de movimento fornecido pelo usuário).Ambos são declarados implicitamente, o que significa que não os forneci, mas diferem na implementação. O construtor de movimento trivial não precisa ser definido - esse é o significado da segunda citação que você forneceu. O compilador pode simplesmente substituí-lo por
std::memmove
call. No entanto, o construtor de movimentação não trivial declarado implicitamente deve ser definido (pelo compilador) para chamar os construtores de movimentação de cada um dos membros da classe.Ainda de outro lado, poderia ser apresentado assim: