【问题标题】:Rules regarding using declarations c++关于使用声明 c++ 的规则
【发布时间】:2021-05-01 14:20:33
【问题描述】:

在阅读了this question 接受的答案后,我想我理解了程序失败的原因,因为使用指令does not actually declare the entity i in the region。但是,使用声明 can be used just like any other nameacts like a declaration 引入的名称。

使用 GCC,这会失败

#include <iostream>


namespace X { int i = 1; }

using X::i;

int main() {
    extern int i;
    i = 2;
    std::cout<<i;
}

但这是可以接受的

#include <iostream>

int i;

int main() {
    extern int i;
    i = 2;
    std::cout<<i;
}

【问题讨论】:

  • 嗯。 MSVC 接受第一个,但 clang-cl 不接受。
  • 仅供参考 - 我没有投反对票。我只是为其他人添加了一些额外的信息。
  • @AdrianMole 对不起,我没有指责你,我只是不知道还有什么要补充的。如果您有建设性的批评,我将不胜感激。大约 10 分钟内投了 2 票而没有太多解释,这有点令人沮丧。
  • NP。 DV 对我和你一样都是一个谜。但是在 SO 上投票是匿名的,要求解释通常是徒劳的。
  • @AdrianMole Sigh 一旦这个问题有两次反对票,没有人会看它,所以我不仅失去了我所拥有的一点名声,没有太多解释,我可能也不会得到更多信息。有时在这里提出问题可能会令人沮丧,我付出了很多努力来具体化,引用其他来源/问题并提供示例。我不明白我做错了什么。

标签: c++ scope namespaces language-lawyer using-declaration


【解决方案1】:

从技术上讲,您给出的示例确实编译,但它无法链接。问题是线

extern int i;

您在这里告诉编译器/链接器的是“将在程序的其他地方定义一个变量i,因此,编译器,如果找不到定义,请不要担心。链接器,我一旦您拥有所有目标文件并将其链接到此处,希望您能找到 i 的定义。”

我们可以使用编译器资源管理器看到这一点:

Without the extern declaration

With the extern declaration

在第二种情况下,i 的声明“遮蔽”了在全局范围内可见的X::i,因此我们得到了指令

mov     DWORD PTR i[rip], 2

而没有 extern 声明,我们得到

mov     DWORD PTR X::i[rip], 2

虽然我不完全确定阴影部分,因为 gcc 和 clang 都没有用 -Wshadow 警告过这一点。无论如何,我们现在看到了为什么第二个示例无法链接:链接器正在尝试找到要在此处使用的 i 的定义,而 X::i 是在全局范围内定义的,i 不是。

【讨论】:

    猜你喜欢
    • 2011-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-28
    • 2018-01-27
    • 1970-01-01
    • 2013-04-22
    相关资源
    最近更新 更多