Clang-tidy check cppcoreguidelines-avoid-const-or-ref-data-members
警告const
限定成员,参考C++核心指南 *C.12不要在可复制或可移动类型中使用数据成员常量或引用 *,请参见
https://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines/avoid-const-or-ref-data-members.html
和/或
https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-constref
强制标记类型为const、&或&&的数据成员**,该类型具有任何复制或移动操作**。
然而,似乎Clang-Tidy检查也适用于那些没有任何复制或移动操作的类型。这有道理吗我的意思是,const
将隐式地使类型不可复制赋值。但是如果类型无论如何都是不可复制的,因为复制构造函数和赋值运算符已经被显式删除,那么const
成员仍然应该被避免吗?
我问这个问题是因为我注意到一个不可复制的类的警告,这个类删除了复制构造函数和赋值运算符,包含一些private
condition_variable
(这就是它不可复制的原因)加上一些private
const
成员只在构造函数中设置(这就是警告的原因)。
class Foo // simplified
{
public:
explicit Foo(int someSetup) : someSetup{someSetup} {}
~Foo() = default;
Foo(const Foo&) = delete;
Foo(Foo&&) = delete;
Foo& operator=(const Foo&) = delete;
Foo& operator=(Foo&&) = delete;
void someMethods() ...;
private:
std::condition_variable someCondition;
const int someSetup; // warning !!!
int someState {};
}
字符串
我应该删除const
吗?我猜这个类的原作者想确保这个值不会改变,这看起来似乎可以理解。另一方面,使其成为非const
不会破坏任何东西,只要没有其他人为该成员添加公共setter。
1条答案
按热度按时间u3r8eeie1#
检查是否过于严格?
问:这种检查是否过于严格,即它的行为是否与其记录的行为相反?
答:是,引用documentation:
此检查实现了C++核心指南中的C.12。
引述规则C.12的标题:
C.12:不要将数据成员设置为const或引用复制或移动类型
(强调我的)。
然而,它报告了问题中的示例,该示例在不可复制、不可移动的类中有一个
const
成员。当然,所有这些信息都已经在你的问题中了。我只是确认你的解释是正确的。
博文链接呢?
如注解中所述,文档以以下内容结束:
进一步阅读:数据成员:永远不要恒定。
链接的帖子认为
const
成员是坏的,不管类型是否可复制。不管你是否同意:1.检查文档没有任何地方说或暗示它实现了不同的规则。它说它实现了C.12。
1.“进一步阅读”的语言使它听起来像是链接到补充材料,而不是改变它之前的文档的意义。我并不惊讶在问这个问题之前被忽视了。
1.即使您点击它,该博客文章中也没有任何内容表明它是由
clang-tidy
开发人员编写的,其参数也没有证明clang-tidy
的行为与规则C.12中指定的行为不同,更不用说与其自己的文档状态不同了。它似乎只是给开发人员的建议,仅此而已。因此,此链接的存在不会改变检查行为不当或其文档错误的结论。
直接删除
const
?这是相当主观的,但我会说**不。
const
限定符简明地传达了成员不改变的意图,并且该意图对读者有帮助。链接的博客文章认为(强调原文):
你甚至可以认为它是自我记录的:“这个数据成员是
const
,所以它不能改变。”但是你知道一个更好的方法来判断一个私有数据成员不能改变吗?* 没有公共API可以更改它!*我强烈反对。直接看到某个东西是
const
要比彻底搜索所有可以访问它的代码并检查其中是否有任何更改要好得多。事实上,这就是const
的全部意义:减轻读者的负担。另一个可能的反对意见是
const
is not immutable。当然,这是正确的,但这与C++的其余设计是一致的,这给了你有用的限制沿着在必要时打破它们的特权。因为const
可以被颠覆而扔掉它,就像是把婴儿和洗澡水一起扔掉。没有一种语言特征不受错误判断的影响。