0

我现在正在通过 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 的第二个声明将输出两次“字符串”,给我的印象是第二个块中声明的 s 也出现在第三个块中。

我还尝试完全删除第三个块的大括号,导致我最初预期的编译错误。但这与声明一个已经存在于第三个块范围内的常量有什么不同呢?如果在较小的范围内没有第二个声明,则常量的声明是否仅延续到较小的范围?

直到此时,我再次浏览了本书中的所有内容,看看我是否遗漏了什么,但我找不到任何关于变量和 const 声明如何受花括号影响的信息。

4

2 回答 2

3

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

于 2017-10-13T16:09:18.463 回答
3

不过,这不仅适用于常量,也没关系。

但这与声明一个已经存在于第三个块范围内的常量有什么不同呢?

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

如果在较小的范围内没有第二个声明,则常量的声明是否仅延续到较小的范围?

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

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

我找不到任何关于变量和常量声明如何受花括号影响的信息。

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

于 2017-10-13T15:58:53.943 回答