【问题标题】:Why can I redefine a const in a smaller scope?为什么我可以在更小的范围内重新定义 const?
【发布时间】:2017-10-13 15:46:29
【问题描述】:

我现在正在使用 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 声明如何受花括号影响的信息。

【问题讨论】:

  • 尝试在前两个}之间添加另一个std::cout &lt;&lt; s &lt;&lt; std::endl;
  • 第二个s 是一个新变量,它从外部作用域中隐藏了一个变量。它也可以有不同的类型。
  • 要查找的关键字是:shadowing。嵌套范围内的s 会遮盖上范围内的s。

标签: c++ visual-studio scope constants accelerated-c++


【解决方案1】:

但这并不只适用于常量,没关系。

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

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

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

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

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

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

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

【讨论】:

  • 谢谢,这有帮助。有点奇怪,这本书希望你知道这一点。刚查了索引,全书都没有提到“影子”或“阴影”。它在主题上也没有真正意义,因为这应该检查你对常量的了解。也许这是一个错字,s = "another string" 应该在第三个街区。
  • 仅供参考,如果您想明确避免阴影,请尝试使用 g++ 的 -Wshadow 选项
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-03
    • 1970-01-01
    • 2022-08-11
    • 1970-01-01
    • 2016-01-13
    相关资源
    最近更新 更多