C++ 重构构造函数以使用初始化列表
我在一个非常大的代码库(超过3M loc)上工作,我们显然有很多类,但大多数类在其构造函数中不使用初始化列表,而是在构造函数体中分配值(一些代码是很久以前编写的,因此这已成为事实上的标准)。也许这些都是由编译器优化的,但我不确定是否真的是这样 我试图推广使用初始化列表,但是有一个庞大的代码库需要更新,所以有没有工具可以自动为我做到这一点?将它指向一个类,找到所有C++ 重构构造函数以使用初始化列表,c++,c++11,visual-studio-2012,automated-refactoring,cppcheck,C++,C++11,Visual Studio 2012,Automated Refactoring,Cppcheck,我在一个非常大的代码库(超过3M loc)上工作,我们显然有很多类,但大多数类在其构造函数中不使用初始化列表,而是在构造函数体中分配值(一些代码是很久以前编写的,因此这已成为事实上的标准)。也许这些都是由编译器优化的,但我不确定是否真的是这样 我试图推广使用初始化列表,但是有一个庞大的代码库需要更新,所以有没有工具可以自动为我做到这一点?将它指向一个类,找到所有m_var=0行并将它们移动到初始化列表(如果需要,创建它) 除了将主体内初始化转换为初始化列表外,是否有办法确定成员变量的初始化顺序正
m_var=0编码>行并将它们移动到初始化列表(如果需要,创建它)
除了将主体内初始化转换为初始化列表外,是否有办法确定成员变量的初始化顺序正确(即,与类的头文件中定义的顺序相同?我希望CppCheck会发现这一点,但似乎没有。您好,我是CppCheck开发人员
Cppcheck也有一个不匹配顺序的检查。但它是一个非决定性的检查
例如:
class Fred {
public:
Fred() : y(0), x(0) {}
int x;
int y;
};
Cppcheck输出:
daniel@debian:~/cppcheck$ ./cppcheck --enable=style --inconclusive 1.cpp
Checking 1.cpp ...
[1.cpp:3] -> [1.cpp:4]: (style, inconclusive) Member variable 'Fred::x' is in the wrong place in the initializer list.
我们的简单检查只会在顺序不匹配时发出警告。这就是为什么它是不确定的。在上面的代码中,初始化顺序实际上并不重要-因为上面代码中的所有成员都是int,所有初始化器都是常量文本。使用类似于OP代码基大小的比例,需要的是a。这是一个将目标语言源文件分解为编译器数据结构(通常为AST),允许您对AST应用转换,然后可以重新生成有效的源代码,包括修改程序的原始注释。请将PST视为大规模重构的工具
好的PTS将允许您编写以下形式的源到源转换:
when you see *this*, replace it by *that* if *condition*
其中,这个和那个用目标语言语法表示,只有源代码与显式语法匹配时才匹配。[这些不是字符串匹配;它们在AST上工作,因此布局不会影响它们的匹配能力]
您需要一个如下所示的关键规则:
rule move_to_initializer(constructor_name:IDENTIFIER,
arguments: argument_list,
initializer_list: initializer,
member_name:IDENTIFIER,
initializer_expression: expression,
statements: statement_list
): constructor -> constructor =
" \constructor_name(\arguments): \initializer_list
{ \member_name = \initializer_expression ;
\statements } "
-> " \constructor_name(\arguments): \initializer_list, \member_name(\initializer_expression)
{ \statements } ";
。DMS是我知道C++的唯一来源,它甚至可以处理MSV方言。
我省略了一个可能必要的“if条件”检查,以确保成员名称确实是类的成员,前提是您的构造函数没有滥用
因为您的构造函数可能没有任何初始值设定项列表,所以您需要一个助手规则来在必要时引入一个初始值设定项列表:
rule move_to_initializer(constructor_name:IDENTIFIER,
arguments: argument_list,
member_name:IDENTIFIER,
initializer_expression: expression,
statements: statement_list
): constructor -> constructor =
" \constructor_name(\arguments)
{ \member_name = \initializer_expression ;
\statements } "
-> " \constructor_name(\arguments): \member_name(\initializer_expression)
{ \statements } ";
{ \member_name = \e ; } "
你总是需要额外的规则来涵盖其他特殊情况,但不应该超过几个
关于检查初始化顺序,您可以使用(DMS)模式触发此类检查:
它需要一个检查顺序的辅助元谓词,如果它们的顺序错误,该谓词会进行投诉。您需要构造函数的名称,以使谓词能够查找相应的类并检查成员的顺序。[DMS向提供了此信息]
或者,您可以简单地使用不同的重写规则对其重新排序:
rule order_initializers(constructor_name:IDENTIFIER,
arguments: argument_list,
initializer_list_prefix: initializer,
initializer_list_suffix: initializer,
member1_name:IDENTIFIER,
initializer1_expression: expression,
member2_name:IDENTIFIER,
initializer2_expression:expression,
statements: statement_list
): constructor -> constructor =
" \constructor_name(\arguments):
\initializer_list_prefix,
\member1_name(\initializer1),
\member2_name(\initializer2),
\initialize_list_suffix
{ \statements } "
->
" \constructor_name(\arguments):
\initializer_list_prefix,
\member2_name(\initializer2),
\member1_name(\initializer1),
\initialize_list_suffix
{ \statements } "
if is_wrong_order(constructor_name,member1_name,member2_name);
这条规则本质上是对初始值设定项进行排序。[注意这是一种冒泡排序:但初始值设定项列表通常不会很长,而且每个构造函数只运行一次。]在使用前面显示的规则将所有初始值设定项从构造函数体中取出后,您将运行此规则。至于第二部分:GCC有-Wreorder
@Biffen做Visual Studio 2012吗?因为这是我正在使用的。据我所知,这不是我所知的,快速谷歌也没有给出任何信息。我将把它留给您来做更多的研究。
rule order_initializers(constructor_name:IDENTIFIER,
arguments: argument_list,
initializer_list_prefix: initializer,
initializer_list_suffix: initializer,
member1_name:IDENTIFIER,
initializer1_expression: expression,
member2_name:IDENTIFIER,
initializer2_expression:expression,
statements: statement_list
): constructor -> constructor =
" \constructor_name(\arguments):
\initializer_list_prefix,
\member1_name(\initializer1),
\member2_name(\initializer2),
\initialize_list_suffix
{ \statements } "
->
" \constructor_name(\arguments):
\initializer_list_prefix,
\member2_name(\initializer2),
\member1_name(\initializer1),
\initialize_list_suffix
{ \statements } "
if is_wrong_order(constructor_name,member1_name,member2_name);