【发布时间】:2019-01-13 07:34:00
【问题描述】:
我目前正在学习 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}相比有什么好处吗?
【问题讨论】:
-
通过引用传递,
Creature c("John");制作一个额外的副本 -
This link 可能是一本有价值的读物,它也涵盖了通过
std::string_view和 SSO。 -
我发现
clang-tidy是一种让自己沉迷于不必要的微优化而牺牲可读性的好方法。这里首先要问的问题是,我们实际上调用了多少次Creature构造函数。
标签: c++