J'apprends le C ++ en ce moment et j'essaie d'éviter de prendre de mauvaises habitudes. D'après ce que je comprends, clang-tidy contient de nombreuses «meilleures pratiques» et j'essaie de m'y tenir du mieux possible (même si je ne comprends pas nécessairement pourquoi elles sont encore considérées comme bonnes), mais je ne suis pas sûr si je comprendre ce qui est recommandé ici.
J'ai utilisé cette classe du tutoriel:
class Creature
{
private:
std::string m_name;
public:
Creature(const std::string &name)
: m_name{name}
{
}
};
Cela conduit à une suggestion de clang-tidy que je devrais passer par valeur au lieu de référence et d'utilisation std::move. Si je le fais, je reçois la suggestion de faire nameune référence (pour assurer qu'il ne soit pas copié à chaque fois) et l'avertissement qui std::moven'aura aucun effet parce nameest un constdonc je dois l' enlever.
La seule façon de ne pas recevoir d'avertissement est de supprimer constcomplètement:
Creature(std::string name)
: m_name{std::move(name)}
{
}
Ce qui semble logique, car le seul avantage constétait d'éviter de jouer avec la chaîne d'origine (ce qui n'arrive pas parce que j'ai passé par valeur). Mais j'ai lu sur CPlusPlus.com :
Notez cependant que -dans la bibliothèque standard- le déplacement implique que l'objet déplacé est laissé dans un état valide mais non spécifié. Ce qui signifie qu'après une telle opération, la valeur de l'objet déplacé ne doit être détruite que ou affectée d'une nouvelle valeur; y accéder donne sinon une valeur non spécifiée.
Imaginez maintenant ce code:
std::string nameString("Alex");
Creature c(nameString);
Parce qu'il nameStringest passé par valeur, std::movene sera invalidé namequ'à l'intérieur du constructeur et ne touchera pas la chaîne d'origine. Mais quels en sont les avantages? Il semble que le contenu ne soit copié qu'une seule fois de toute façon - si je passe par référence lorsque j'appelle m_name{name}, si je passe par valeur lorsque je le passe (et ensuite il est déplacé). Je comprends que c'est mieux que de passer par valeur et de ne pas utiliser std::move(car il est copié deux fois).
Donc deux questions:
- Ai-je bien compris ce qui se passe ici?
- Y a-t-il un avantage à utiliser
std::movele dépassement par référence et simplement appelerm_name{name}?
clang-tidyun excellent moyen de devenir obsédé par les microoptimisations inutiles au détriment de la lisibilité. La question à se poser ici, avant toute autre chose, est de savoir combien de fois appelons-nous réellement le Creatureconstructeur.
Creature c("John");fait une copie supplémentaire