为什么编译器会警告在初始化列表中隐藏成员?

Tre*_*key 6 c++ g++ clang compiler-warnings

使用与其初始化的数据成员具有相同标识符的构造函数参数.如果在初始化列表中使用这两个,则认为它是安全的,并且不会发生"阴影".

但是,请参考以下示例:

struct A{
  A(int a, int b);
  int a, b;
};

A::A(int a, int b)
: a(a)
, b(b)
{}

int main(){}
Run Code Online (Sandbox Code Playgroud)

用g ++看到的警告:

g++ -Wshadow --std=c++1z -o main main.cpp 
main.cpp: In constructor ‘A::A(int, int)’:
main.cpp:8:18: warning: declaration of ‘b’ shadows a member of ‘A’ [-Wshadow]
 A::A(int a, int b)
                  ^
main.cpp:4:10: note: shadowed declaration is here
   int a, b;
          ^
main.cpp:8:18: warning: declaration of ‘a’ shadows a member of ‘A’ [-Wshadow]
 A::A(int a, int b)
                  ^
main.cpp:4:7: note: shadowed declaration is here
   int a, b;
Run Code Online (Sandbox Code Playgroud)

用clang看警告:

clang++ -Wshadow --std=c++1z -o main t.cpp
main.cpp:8:10: warning: declaration shadows a field of 'A' [-Wshadow]
A::A(int a, int b)
         ^
main.cpp:4:7: note: previous declaration is here
  int a, b;
      ^
main.cpp:8:17: warning: declaration shadows a field of 'A' [-Wshadow]
A::A(int a, int b)
                ^
main.cpp:4:10: note: previous declaration is here
  int a, b;
Run Code Online (Sandbox Code Playgroud)

我没有对构造函数体中的数据成员做任何事情 - 所以为什么我会收到这些警告?

我想保留警告标志以捕获合法的意外,但这些特殊情况造成了太多的虚假噪音.这些警告是否有效?

Tar*_*ama 16

虽然你没有做任何事情,其中的阴影可能会伤害你现在,你是在和自己的一些维护问题.

如果Maintainer Joe出现并需要进行如下更改:

A::A(int a, int b)
: a(a)
, b(b)
{
    storeReference(a);
}
Run Code Online (Sandbox Code Playgroud)

哎呀!他只是存储了对参数的引用而不是数据成员.

编译器本身没有告诉你你做错了什么,它告诉你你可能想要改变你的名字,这样你将来就不会有任何问题.

举个例子,我建议选择一个命名约定来消除歧义并坚持下去.就个人而言,我喜欢把m_成员数据放在前面,但其他人更喜欢以_成员数据或构造函数参数为后缀.

  • 这还算公平。我本来希望编译器可以保持沉默,直到 Joe 在正文中添加了一些确实很危险的东西。一个空白的身体似乎微不足道,而且很常见,不应该发出警告。也许这种行为没有我想象的那么受欢迎。 (3认同)