Scope ambiguity in nested if

2019-07-12 12:48发布

问题:

Let's say one has a class Foo such as

class Foo {
public:
  void bar();
  operator bool() const { return true; }
};

then one can do

if(Foo foo = Foo())
{
  if(Foo foo = Foo())
  {
    foo.bar();
  }
}

Now I'm having trouble grasping the scope resolution going on here (I would've expected a compiler error for redeclaring foo).

I expect foo.bar() to execute on the second foo (its scope is "closer") but am I garanteed that it's actually a different object than the first foo? Furthermore, are they each independently disposed (their destructor called) at the end of their respective if blocks?

回答1:

C++ is quite happy for you to declare a variable with the same name, as long as it is inside a nested scope so there is no ambiguity.

I expect foo.bar() to execute on the second foo (its scope is "closer")

You are correct

but am I garanteed that it's actually a different object than the first foo?

Yes

Furthermore, are they each independently disposed (their destructor called) at the end of their respective if blocks?

Yes



回答2:

I expect foo.bar() to execute on the second foo (its scope is "closer")

Correct.

but am I garanteed that it's actually a different object than the first foo?

Yes.

Furthermore, are they each independently disposed (their destructor called) at the end of their respective if blocks?

Yes, you've got it.



回答3:

The use of if statements and class object initialization in your example tends to obscure the relevant point, which is that declarations in inner scopes are perfectly legal and hide declarations of the same name in outer scopes.

A perhaps clearer example:

#include <iostream>
int main() {
    const int x = 10;
    std::cout << "outer x is " << x << "\n";
    {
        const double x = 12.34;
        std::cout << "    inner x is " << x << " (it hides the outer x)\n";
    }
    std::cout << "outer x is still " << x << " (inner x no longer exists)\n";
}

The output is:

outer x is 10
    inner x is 12.34 (it hides the outer x)
outer x is still 10 (inner x no longer exists)

Note that the inner and outer xs aren't even of the same type.

Though this is legal, it's usually not a good idea; the compiler has no problem with it, but it can be confusing to human readers. If you compile with g++ -Wshadow, you'll get warnings:

c.cpp: In function ‘int main()’:
c.cpp:6:22: warning: declaration of ‘x’ shadows a previous local
c.cpp:3:15: warning: shadowed declaration is here


标签: c++ scope