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

Why does the compiler warn about shadowing a member in initalization lists?

采用与正在初始化的数据成员具有相同标识符的构造函数参数。如果两者都用在一个初始化列表里面,就认为是安全的,不会出现"shadowing"。

但是,举个例子:

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

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

int main(){}

使用 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;

用 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;

我没有对构造函数主体中的数据成员执行任何操作——那么为什么我会收到这些警告?

我想启用警告标志以捕捉合法的事故,但这些特殊情况导致了太多错误的噪音。这些警告是否有效?

它抱怨是因为 a(a)b(b) - 结构成员的名称应与构造函数的参数名称不同。然后构造看起来像 mA(a)mB(b)

虽然您现在没有做任何阴影可能会伤害您的事情,但您正在为一些维护问题设置自己。

如果维护者 Joe 出现并且需要进行如下更改:

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

糟糕!他只是存储了对参数而不是数据成员的引用。

编译器并没有告诉你你本身做错了什么,它只是告诉你你可能想要更改你的名字,这样你以后就不会遇到问题了。

我个人建议选择一种命名约定来消除歧义并坚持使用。我个人喜欢把m_放在member data的前面,但是其他人更喜欢在member data或者constructor param后面加上_