为什么我可以在更小的范围内重新定义一个 const?

Why can I redefine a const in a smaller scope?

我现在正在学习 Accelerated C++,我遇到了对范围和代码块的根本性缺乏理解。

第 1 章末尾有一个练习,要你决定这段代码是否会 运行:

#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;
}

我确定不会,但确实如此。我的爱好编程经验是,块中声明的变量可用于包含在其中的其他块,但不能用于块外的其他块。

这至少有一半是对的,因为删除 s 的第二个声明将输出 "a string" 两次,给我的印象是第二个块中声明的 s 也出现在第三个块中.

我也试过完全删除第三个块的大括号,结果出现了我最初预期的编译错误。但这与声明一个已经存在于第三块范围内的常量有何不同?如果在较小的范围内没有第二个声明,常量的声明是否仅适用于较小的范围?

到目前为止,我已经仔细阅读了本书中的所有内容,以查看是否遗漏了什么,但是我找不到任何关于变量和常量声明如何受花括号影响的信息。

虽然这不仅仅适用于常量,但这并不重要。

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

您正在引入另一个作用域,其中变量 s 尚未定义,因此定义一个是完全合法的。如果你删除一个,你会得到一个重新定义错误,因为你已经在相同的范围内有一个 s

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

不是真的。你的第二个 s 隐藏 第一个。从技术上讲,它们都存在,但您无法访问第一个。有时您会在范围解析运算符的帮助下这样做,但在您的情况下,不会。

// 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.

大括号通常会引入一个新的作用域(尽管也有一些例外)。只要具有给定名称的变量未在当前范围内定义,您就可以定义它。在它之外的作用域中是否存在同名变量并不重要,但您的编译器可能会警告您。

Java 和 C++ 是为数不多的允许这样做的语言之一。 C# 不允许这样做。 它被称为可变阴影。如果您在较小的内部块中声明一个与外部块变量具有相同名称的变量,那么您将获得名称屏蔽。 所以你有一个 const 变量并不重要,因为内部变量完全是一个不同的变量。