C++ 为什么在定义的编译和链接之前引用外部实例的程序
C++ Why program with extern instance referenced before defined compiles and links
问题可以通过一个简单的例子来显示:
extern A<bool> a;
B b(a);
A<bool> a("a");
在头文件中:
template<typename T>
class A {
public:
A(const char * name) : m_name(name) {}
const char * name() const {
return m_name;
}
...
...
private:
const char * m_name;
};
class B {
public:
B(A<bool> & a) {
printf("%s = %pn", a.name(), &a);
}
};
代码实际编译、链接和生成:
(null) = 0044F604
演示
我想知道这是否不应该被编译器捕获并失败。
有问题的编译器是gcc 9.2.0 (mingw-w64-i686)
。
在C++中,同一翻译单元中的全局对象按其定义的顺序进行初始化(尽管TU的顺序未定义(。参见 [basic.start.init]/2:
。在单个翻译单元中定义的有序初始化变量应按照其在翻译单元中的定义顺序进行初始化。
另一方面,静态存储持续时间的对象的存储是在程序加载时分配的,因此每个全局对象从一开始就有一个地址。
通常,在C++中,允许引用尚未初始化的对象,但访问它是未定义的行为。通常不需要对未定义的行为进行诊断。
在您的情况下,可以使用对A
的引用构造B
,并且可以保存传入的引用以供以后使用:
class B {
A<bool> & a_;
public:
B(A<bool> & a) : a_(a) { }
void run() {
printf("%s = %pn", a_.name(), &a_);
}
};
- 传递和使用对未初始化对象的引用并没有错。标准明确允许这样做。
- 程序员有责任以标准允许的有限方式之一使用此类引用。如果使用情况超出允许的范围,编译器不需要抱怨。相反,执行此操作的程序的行为是未定义的。
有关详细信息,请参阅 basic.life/6 和 basic.life/7。
相关文章:
- 在函数内创建的对象的范围 - 如果在函数外部存储和访问引用,它们是否有效?
- 使用带有 CMake 和 Conan 的外部库的未定义引用
- 函数 _main (OPENGL C++) 中引用的未解析的外部符号 ________
- C++ 为什么在定义的编译和链接之前引用外部实例的程序
- 如果 copts 不允许系统路径,如何引用外部依赖项使用的系统库?
- 函数 LNK2019 "int __cdecl __scrt_common_main_seh(void)" 中引用的未解析外部符号主错误 (?__scrt_common_main_seh@@YAHXZ
- 函数_wmain中引用未解析的外部符号_RasSetEntryPropertiesW@24
- C++ 链接器错误 LNK 2019 函数中引用的未解析的外部符号
- 如何修复"未解析的外部符号"公共:void__thiscall canoid::getinput(void)"(?Getinput@Canoid@@QAEXXZ) 在函数 _main C++ 中引用
- C 引用C++外部
- 使用静态变量未解析的外部符号/未定义的引用时出错
- 未解析的外部符号__imp_glewInit函数 main 中引用
- 在虚幻引擎中引用外部库时出现运行时错误
- 具有仅在某些情况下引用外部变量的属性的类
- 为什么静态本地对象可以通过指针或外部引用访问?
- 函数中引用LNK2019未解析的外部符号 dbbind 的错误
- lnk2019未解决的外部符号_sdl_init在函数_sdl_main中引用
- C++:外部对象循环引用
- 为什么对非类型模板参数的引用需要外部链接
- 如何在qt qbs中引用外部库依赖关系