This is pretty valid, because they're in different scopes. For the member initializer list A(A)
, the 1st A
is in the scope of the class, then the data member A
will be found; the 2nd A
(which is putted in the parentheses) is in the scope of the constructor, then the parameter A
will be found (and hide the data member with the same name).
Quotes from the standard,
$15.6.2/2 Initializing bases and members [class.base.init]:
In a mem-initializer-id an initial unqualified identifier is looked up in the scope of the constructor's class and, if not found in that scope, it is looked up in the scope containing the constructor's definition.
and $15.6.2/15 Initializing bases and members [class.base.init]:
Names in the expression-list or braced-init-list of a mem-initializer
are evaluated in the scope of the constructor for which the
mem-initializer is specified. [ Example:
class X {
int a;
int b;
int i;
int j;
public:
const int& r;
X(int i): r(a), b(i), i(i), j(this->i) { }
};
initializes X::r
to refer to X::a
, initializes X::
b with the
value of the constructor parameter i
, initializes X::i
with the
value of the constructor parameter i
, and initializes X::j
with the
value of X::i
; this takes place each time an object of class X is
created. — end example ] [ Note: Because the mem-initializer are
evaluated in the scope of the constructor, the this
pointer can be
used in the expression-list of a mem-initializer to refer to the
object being initialized. — end note ]