c++ - 关于使用声明 c++ 的规则
问题描述
在阅读了这个问题的接受答案后,我想我理解了程序失败的原因,因为 using 指令实际上并未声明i
该区域中的实体。然而,由 using 声明引入的名称可以像任何其他名称一样使用,并且可以像声明一样使用。
使用 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;
}
解决方案
从技术上讲,您给出的示例确实可以编译,但无法链接. 问题是线路
extern int i;
您在这里告诉编译器/链接器的是“i
程序中的其他地方将定义一个变量,因此,编译器,如果找不到定义,请不要担心。链接器,我希望您找到定义一旦您拥有i
所有目标文件并将其链接到此处。”
我们可以使用编译器资源管理器看到这一点:
在第二种情况下,i
“阴影”的声明X::i
在全局范围内可见,所以我们得到指令
mov DWORD PTR i[rip], 2
而没有 extern 声明,我们得到
mov DWORD PTR X::i[rip], 2
虽然我不完全确定阴影部分,因为 gcc 和 clang 都没有警告过-Wshadow
. 无论如何,我们现在看到了为什么第二个示例无法链接:链接器试图在i
此处找到要使用的定义,而 whileX::i
是在全局范围内定义的,但i
不是。
推荐阅读
- java - “使用带参数的构造函数 NO_CONSTRUCTOR 实例化 java.util.List 失败”,
- python - 如何将没有内存转储的大型 numpy 文件加载到 kaggle 笔记本中?
- python - 无法使用修改后的 LLE、hessian LLE 和局部切线空间对齐来分配那么多内存
- ios - SWIFT:让语音停止阅读截断的字符串
- c++ - C++ - 如何记住文件是否已被移动?
- express - 尝试在 Heroku 中为 MERN 应用程序设置 package.json
- matplotlib - 如何在网格外绘制时保持 matplotlib 网格的约束?
- javascript - 表单电子邮件与脚本和 html 合并,对多人和不同的链接进行编码
- list - 来自值 var 的 Ansible List 访问权限
- java - 将密码存储在 JVM 的 RAM 中:有多大问题?