Ich lerne gerade C ++ und versuche, schlechte Gewohnheiten zu vermeiden. Soweit ich weiß, enthält clang-tidy viele "Best Practices" und ich versuche, mich so gut wie möglich an sie zu halten (obwohl ich nicht unbedingt verstehe, warum sie noch als gut gelten), aber ich bin mir nicht sicher, ob ich es tue Verstehe, was hier empfohlen wird.
Ich habe diese Klasse aus dem Tutorial verwendet:
class Creature
{
private:
std::string m_name;
public:
Creature(const std::string &name)
: m_name{name}
{
}
};
Dies führt zu einem Vorschlag von clang-tidy, dass ich Wert anstelle von Referenz und Verwendung übergeben soll std::move. Wenn ich das tue, erhalte ich den Vorschlag zu machen , nameeine Referenz (um sicherzustellen , dass nicht jedes Mal kopiert bekommt) und die Warnung , dass std::movekeine Auswirkungen haben , da nameeine ist , constdamit ich es entfernen sollte.
Die einzige Möglichkeit, keine Warnung zu erhalten, besteht darin, sie constvollständig zu entfernen :
Creature(std::string name)
: m_name{std::move(name)}
{
}
Was logisch erscheint, da der einzige Vorteil darin constbestand, das Durcheinander mit der ursprünglichen Zeichenfolge zu verhindern (was nicht passiert, weil ich den Wert übergeben habe). Aber ich habe auf CPlusPlus.com gelesen :
Beachten Sie jedoch, dass das Verschieben in der Standardbibliothek impliziert, dass das verschobene Objekt in einem gültigen, aber nicht angegebenen Zustand belassen wird. Dies bedeutet, dass nach einer solchen Operation der Wert des verschobenen Objekts nur zerstört oder ein neuer Wert zugewiesen werden sollte. Wenn Sie andernfalls darauf zugreifen, erhalten Sie einen nicht angegebenen Wert.
Stellen Sie sich nun diesen Code vor:
std::string nameString("Alex");
Creature c(nameString);
Da nameStringder Wert übergeben wird, std::movewird er nur nameinnerhalb des Konstruktors ungültig und berührt nicht die ursprüngliche Zeichenfolge. Aber was sind die Vorteile davon? Es scheint, als würde der Inhalt sowieso nur einmal kopiert - wenn ich beim Aufrufen als Referenz übergebe m_name{name}, wenn ich beim Übergeben den Wert übergebe (und dann wird er verschoben). Ich verstehe, dass dies besser ist, als den Wert zu übergeben und nicht zu verwenden std::move(weil es zweimal kopiert wird).
Also zwei Fragen:
- Habe ich richtig verstanden, was hier passiert?
- Gibt es einen Vorteil
std::move, wenn Sie das Übergeben als Referenz verwenden und nur anrufenm_name{name}?
std::string_viewund SSO.
clang-tidyeine großartige Möglichkeit ist, mich auf Kosten der Lesbarkeit von unnötigen Mikrooptimierungen besessen zu machen. Die Frage, die hier vor allem gestellt werden muss, ist, wie oft wir den Konstruktor tatsächlich aufrufen Creature.
Creature c("John");macht eine zusätzliche Kopie