A julgar pelos comentários
habr.com/en/post/460831/#comment_20416435 no próximo post e a discussão que se desenrolou lá, o artigo sobre como transmitir corretamente argumentos ao construtor ou setter não prejudicará Habré. O StackOverflow tem muito material semelhante, mas não me lembro de algo aqui.
Porque o exemplo desse artigo está completamente correto e o autor do artigo está absolutamente certo. Aqui está um exemplo:
Esse código permite cobrir todas (bem, quase todas) as opções possíveis para o uso da classe:
std::string first{"abc"}, last{"def"}; person p1{first, last};
Compare com o método antigo, quando passado por const &: é definitivamente pior, porque exclui a opção (3):
Uma alternativa com && também é pior, mas na direção oposta:
Se você não tem medo de uma explosão combinatória, pode dar uma chance a && (mas por quê? Não haverá ganho real de velocidade, o otimizador não cochila):
Ou a mesma coisa, apenas com modelos (mas novamente, por quê?):
Mesmo se você não tiver std :: string, mas algum objeto de sua própria classe grande escrita e desejar que as pessoas a movam (e não copiem), nesse caso, é melhor proibir o construtor de copiar essa classe grande do que passá-la para todos os lugares por &&. Isso é mais confiável e o código é mais curto.
Por fim, algumas opções sobre como NÃO vale a pena:
E assim não:
Por que isso está acontecendo, qual é o princípio fundamental? É simples: um objeto, como regra, deve POSSUIR suas propriedades.
Se o objeto não quiser possuir algo, ele poderá possuir shared_ptr para esse "algo". A propósito, neste caso shared_ptr também deve ser passado por valor, e não por link constante - não há diferença com o primeiro exemplo no início do artigo:
Observe: std :: move para shared_ptr é completamente legal, elimina a sobrecarga de bloquear o contador de links shared_ptr na memória (centenas de ciclos de CPU) e seu incremento. Não afeta a vida útil do objeto e outros links para ele. Mas (X) pode ser feito, é claro, apenas se o link psh no código abaixo não for mais necessário.
Moral: não use const & em geral. Olhe de acordo com as circunstâncias.
PS
Use {} em vez de () ao passar parâmetros do construtor. Juventude elegante e moderna.
PPS
Em conclusão, mais uma coisa: std :: move () na verdade não move nada e, por si só, se traduz em zero instruções do assembler. Tudo o que std :: move () faz é colocar um "rótulo adesivo" especial no link, transformando-o em uma referência de valor && -. Além disso, é possível com esse rótulo "combinar" separadamente o tipo de parâmetro de função (por exemplo, ter uma sobrecarga de função separada para o parâmetro && - e separada para o parâmetro &). O significado do rótulo && - é permitir que o código de chamada informe o chamado: “se você quiser, pode comer o valor desse link, não preciso mais dele; mas somente se você comer, deixe os ossos, então ainda preciso chamar o destruidor do esqueleto restante. " Com o mesmo sucesso, seria possível transmitir & -links comuns (você também pode usar o objeto para "comê-los"), mas com && semântica são melhores, porque você não vai confundir: onde você pode comer e onde você só pode cheirar.
Nesse sentido, o nome std :: move () deve ser reconhecido como extremamente malsucedido. Seria correto chamá-lo de std :: eat_me_if_you_want () ou std :: bon_appetit (). Mas std :: move () é mais curto.