Estou aprendendo C ++ no momento e tento evitar os maus hábitos. Pelo que entendi, o clang-tidy contém muitas "práticas recomendadas" e tento segui-las da melhor maneira possível (embora ainda não entenda necessariamente por que são consideradas boas), mas não tenho certeza se estou entenda o que é recomendado aqui.
Usei esta aula do tutorial:
class Creature
{
private:
std::string m_name;
public:
Creature(const std::string &name)
: m_name{name}
{
}
};
Isso leva a uma sugestão do clang-tidy de que eu deveria passar por valor em vez de referência e uso std::move. Se o fizer, recebo a sugestão de fazer nameuma referência (para garantir que não seja copiado todas as vezes) e o aviso de que std::movenão terá qualquer efeito por nameser um, constportanto, devo removê-lo.
A única maneira de não receber um aviso é removendo por constcompleto:
Creature(std::string name)
: m_name{std::move(name)}
{
}
O que parece lógico, já que o único benefício de constera evitar mexer na string original (o que não acontece porque passei por valor). Mas eu li no CPlusPlus.com :
Embora, observe que, na biblioteca padrão, a movimentação implica que o objeto movido é deixado em um estado válido, mas não especificado. O que significa que, após tal operação, o valor do objeto movido só deve ser destruído ou atribuído a um novo valor; acessá-lo de outra forma produz um valor não especificado.
Agora imagine este código:
std::string nameString("Alex");
Creature c(nameString);
Como nameStringé passado por valor, std::movesó vai invalidar namedentro do construtor e não tocar na string original. Mas quais são as vantagens disso? Parece que o conteúdo é copiado apenas uma vez - se eu passar por referência quando chamo m_name{name}, se eu passar por valor quando eu o passar (e então ele é movido). Eu entendo que isso é melhor do que passar por valor e não usar std::move(porque ele é copiado duas vezes).
Portanto, duas questões:
- Eu entendi corretamente o que está acontecendo aqui?
- Existe alguma vantagem em usar
std::movepassar por referência e apenas ligarm_name{name}?
clang-tidyé uma ótima maneira de ficar obcecado por microotimizações desnecessárias em detrimento da legibilidade. A questão a fazer aqui, antes de mais nada, é quantas vezes realmente chamamos o Creatureconstrutor.
Creature c("John");faz uma cópia extra