Why can I redefine a const in a smaller scope?

1.1k views Asked by At

I'm working my way through Accelerated C++ right now, and I've encountered a fundamental lack of understanding regarding scope and code blocks on my part.

There is an exercise at the end of chapter 1 that wants you to decide whether this code is will run:

#include <iostream>
#include <string>

int main()
{
    {
        const std::string s = "a string";
        std::cout << s << std::endl;
        {
            const std::string s = "another string";
            std::cout << s << std::endl;
        }
    }
    return 0;
}

I was sure it wouldn't, but it does. My hobby programming experience was that variables declared in a block are available to other blocks contained within it, but not those outside of it.

And that must be at least half-true, since removing the second declaration of s will output "a string" twice, giving me the impression that s as declared in the second block is also present in the third block.

I also tried removing the braces of the third block entirely, resulting in the compilation error I expected in the first place. But how is that different from declaring a constant that already exists in the scope of the third block? Does the declaration of a constant only carry over to a smaller scope if there is no second declaration in that smaller scope?

I've gone through everything in the book up until this point again to see if I missed something, but I can't find any information on how variable and const declarations are affected by curly braces.

2

There are 2 answers

2
Rakete1111 On BEST ANSWER

This doesn't just apply to constants though, that doesn't matter.

But how is that different from declaring a constant that already exists in the scope of the third block?

You are introducing another scope, where the variable s has not been defined, so it is perfectly legal to define one. If you remove one, you'll get a redefinition error, because you already have an s in the same scope.

Does the declaration of a constant only carry over to a smaller scope if there is no second declaration in that smaller scope?

Not really. Your second s is shadowing the first one. Technically, both of them exist, but you have no way of accessing the first one. Sometimes you do, with the help of the scope resolution operator, but in your case, no.

// global scope
int a;
void f() {
    int a = 0;
    a = 4; // local 'a'.
    ::a = 4; // global 'a'.
}

I can't find any information on how variable and const declarations are affected by curly braces.

Curly braces in general introduce a new scope (although there are some exceptions). As long as a variable with a given name is not defined in the current scope, you can define it. It doesn't matter if there is a variable with the same name in a scope outside of it, but your compiler will likely warn you about it.

0
SurrealSerenade On

Java and C++ are one of the few that allows this. C# does not allow this. It is called Variable Shadowing. If you declare a variable with same name in a smaller inner block as outer blocks variable then you get name masking. So it doesnt matter that you have a const variable because the inner variable is a different variable altogether.