Я изучаю C++ на данный момент и стараюсь избегать появления вредных привычек. Из того, что я понимаю, clang-tidy содержит много "лучших практик", и я стараюсь придерживаться их как можно лучше (хотя я не всегда понимаю, почему они считаются хорошими), но я не уверен, если я понять, что рекомендуется здесь.
Я использовал этот класс из учебника:
class Creature
{
private:
std::string m_name;
public:
Creature(const std::string &name)
: m_name{name}
{
}
};
Это приводит к предположению от clang-tidy, что я должен передавать значение вместо ссылки и использовать std::move
. Если я делаю, я получаю предложение сделать name
ссылки (для того чтобы он не копируется каждый раз) и предупреждение, что std::move
не будет иметь никакого эффекта, потому что name
является const
, поэтому я должен удалить его.
Единственный способ, которым я не получаю предупреждение, - это удалить const
полностью:
Creature(std::string name)
: m_name{std::move(name)}
{
}
Это кажется логичным, поскольку единственное преимущество const
состояло в том, чтобы предотвратить испорченность исходной строки (чего не происходит, потому что я прошел по значению). Но я читал на CPlusPlus.com:
Хотя обратите внимание, что -in стандартное library- перемещение подразумевает, что перемещенный объект остается в действительном, но неуказанном состоянии. Это означает, что после такой операции значение перемещенного объекта должно быть уничтожено или назначено новое значение; доступ к нему в противном случае дает неопределенное значение.
Теперь представьте этот код:
std::string nameString("Alex");
Creature c(nameString);
Поскольку nameString
передается по значению, std::move
будет только отменять name
внутри конструктора и не трогать исходную строку. Но каковы преимущества этого? Кажется, что контент копируется только один раз - если я m_name{name}
ссылку, когда я вызываю m_name{name}
, если я m_name{name}
по значению при его передаче (а затем он будет перемещен). Я понимаю, что это лучше, чем передача по значению и не использование std::move
(потому что он дважды копируется).
Итак, два вопроса:
- Правильно ли я понял, что здесь происходит?
- Есть ли потенциал для использования
std::move
overm_name{name}
by reference и просто вызовm_name{name}
?