cppcheck vs clang整洁:显式构造函数initializer_list
cppcheck vs clang-tidy : explict constructor initializer_list
当我运行工具clang-tidy-3.8和cppcheck-1.72时,在以下代码下:
#include <initializer_list>
#include <string>
#include <iostream>
using string_list = std::initializer_list<std::string>;
class Foo {
public:
explicit Foo(const string_list& strings) {
for (const auto& ss : strings) {
std::cout << ss << std::endl;
}
}
};
clang-tidy-3.8输出:
$>clang整洁-checks='*main.cpp--std=c++11
警告:初始值设定项列表构造函数不应声明为显式[google显式构造函数]显式Foo(const-string_list&string)
但是,如果我删除关键字显式,则cppcheck-1.72报告:
$>cppcheck-main.cpp--language=c++--std=c++11--enable=all
(style)类"Foo"有一个具有1个非显式参数的构造函数。
我在谷歌Cpp指南上阅读:
不能用单个参数调用的构造函数通常应该省略显式。采用单个std::initializer_list参数的构造函数也应该省略显式,以便支持复制初始化(例如,MyType m={1,2};)。
哪种工具是正确的根据C++标准?
正如@KerrekSB所说,这取决于你想要执行的构建风格。
如果您使初始值设定项列表构造函数explicit
,则
- 您不允许
YourType A = {a, b, c};
- 但只允许
YourType A({a, b, c});
(或YourType A{{a, b, c}};
)(我认为有些编译器接受YourType A{a, b, c}
,但我发现它不一致。)
如果不将其标记为explict
,两种情况都是允许的。
有些人主张永远不要在(类的)构造函数中使用=
(甚至不用于初始值设定项列表参数),因此这最终是您通过标记explicit
来强制执行的样式。
标记explicit
的另一个重要副作用是,您必须考虑到,您将无法将原始初始值设定项列表作为函数参数来传递,以代替构造的对象(这可能是限制性的,但可能是进一步样式考虑的一部分)。例如fun(arg1, arg2, {a, b, c})
与fun(arg1, arg2, YourType({a, b, c}))
。
还要注意,例如,std::vector::vector(std::initializer_list)
(或任何其他std容器)是而不是标记为explicit
。
我的经验法则是,当右手边可以表示为"0"时,我允许构造函数中的CCD_;忠实地";具有构造类型并且计算复杂度低(例如小于O(N log N)或O(N^2))。IMO没有多少情况下可以通过初始值设定项列表来实现这一点。我遇到的唯一例子是1)数组或列表(包括std::vector
)的一些转世2)无序线性容器(但IMO不包括有序容器)。3) 多维数组(嵌套初始值设定项列表)。4) 元组(尽管该语言中存在非齐次初始值设定项列表)。
(有了这个规则,我认为std::set
不显式是一个错误,因为std::set
将在幕后重新排序)。
在实践中,我所做的是使用对cppcheck
警告进行内联抑制的注释,我觉得注释对于任何隐式单参数构造函数来说都是必要的。
// cppcheck-suppress noExplicitConstructor ; because human-readable explanation here
YourType(std::initializer_list<value_type> il){...}
并使用选项CCD_ 20运行CCD_。
(参见http://cppcheck.sourceforge.net/manual.pdf#page=19)
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 没有用于初始化C++中的变量模板的匹配构造函数
- 初始化具有非默认构造函数的std::数组项的更好方法
- 当从函数参数中的临时值调用复制构造函数时
- 在c++构造函数中使用随机字符串生成器
- 一对向量构造函数:初始值设定项列表与显式构造
- 从构造函数抛出异常时如何克服内存泄漏
- 我不明白为什么我声明一个空的内部结构并将其传递给构造函数
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 具有默认模板类型的默认构造函数的类型推导
- 使用dynamic_cast和构造函数时出错
- 反对"initialize()"方法而不是构造函数的参数
- 在 T 的构造函数中"initialize" 具有 *this = T() 的 T 类型的对象是否安全?