我目前正在学习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上阅读:
尽管要注意-在标准库中-移动意味着从中移出的对象处于有效但未指定的状态。这意味着在执行此操作后,仅应销毁移出对象的值或为其分配新值;否则访问它会产生未指定的值。
现在想象一下这段代码:
std::string nameString("Alex");
Creature c(nameString);
因为nameString
通过值传递,所以std::move
只会name
在构造函数内部无效,而不会接触原始字符串。但是,这样做的好处是什么?似乎该内容仅被复制一次-如果我在调用时通过引用传递m_name{name}
,如果在传递时通过值传递(然后它被移动)。我知道这比按值传递而不使用std::move
(因为它被复制两次)更好。
有两个问题:
- 我是否正确理解这里发生的事情?
- 使用
std::move
按引用传递和仅调用有任何好处m_name{name}
吗?
clang-tidy
这是让自己沉迷于不必要的微优化的一种好方法,但是却牺牲了可读性。首先要问的问题是,我们实际调用Creature
构造函数多少次。
Creature c("John");
制作了一个额外的副本