views:

319

answers:

2

Some code first:

class CInner {
public:
    CInner( const CInner& another ) { //impl here }
private:
    // some member variables
}

class COuter {
public:
    COuter( const CInner& inner ) : inner( inner ) {}
private:
    CInner inner;
}

Yes, in COuter::COuter( const CInner& ) the parameter has the same name as the member variable.

In VC++ that works - VC++ gets the idea that it is only reasonable to initialize the member variable with the parameter and that's what happens - CInner::inner gets initialized with the parameter. But when the same is compiled with GCC it is interpreted in another way: GCC initializes CInner::inner with itself and so it is left uninitialized.

Which of the compilers is right?

+17  A: 

It is not really about some specific compiler deciding what's reasonable and what's not. The language specification explicitly says that in inner(inner) used in the constructors initializer list the first inner should be looked up in class scope (i.e. resolve to COuter::inner), while the second innershould be looked up in the constructor scope (i.e. resolve to constructor parameter inner).

This is what you described as VC++ behavior. However, I find it hard to believe that GCC would behave incorrectly in this case (unless you have some weird old version of GCC). Are you sure you haven't misinterpreted GCC's behavior somehow?

AndreyT
This issue can be avoided by simply using two different variable names. The different names also add to the readability, IMHO.
Thomas Matthews
+8  A: 

Visual C++ is correct. I suspect you're using an older version of gcc for your test -- at least as I recall, recent ones do this correctly. This is covered in §12.6.2/7 of the standard, which gives the following 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, [ ...]

Jerry Coffin
It may be right but it is ugly as all hell and makes it more difficult to read than needs be.
Craig
@Craig: How so? I'd say "difficult to read" is when you have to keep track of two different names for what's conceptually the same object. Of course the member and the constructor parameter should have the same name. They're *supposed* to be the same.
jalf
i keep the practice of keeping my private member variables in a certain format such as m_variable, i think this is pretty standard and it avoids these conflicts.I just don't think it makes sense to have two variables with the same name; even if one if a member variable and one is a parameter. Everyone has a point where they think things just become too difficult to bother with, for me it is having two variable with the same name in the same function, plus m_i(i) is easier to conceptualize than i(i).
Craig