繁体   English   中英

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 = %p\n", a.name(), &a);
        }
};

代码实际编译、链接并生成:

(null) = 0044F604

演示

我想知道这是否不应该被编译器捕获并失败。

有问题的编译器是gcc 9.2.0 (mingw-w64-i686)

  1. 传递和使用对未初始化对象的引用并没有错。 标准明确允许这样做。
  2. 程序员有责任以标准允许的有限方式之一使用这样的引用。 如果使用超出允许范围,编译器不需要抱怨。 相反,执行此操作的程序的行为是未定义的。

有关详细信息,请参阅basic.life/6basic.life/7

在 C++ 中,同一翻译单元中的全局对象按照它们定义的顺序进行初始化(尽管跨 TU 的顺序是undefined )。 [basic.start.init]/2

...在单个翻译单元中定义的具有有序初始化的变量应按照它们在翻译单元中的定义顺序进行初始化。

在另一方面,静态存储持续时间的对象存储在程序加载时间分配的,所以每一个全局对象从一开始的地址。

通常,在 C++ 中,允许引用尚未初始化的对象,但访问它是未定义的行为。 通常不需要对未定义行为进行诊断。

在您的情况下, B可以使用对A的引用来构造,并且它可以保存传入的引用以供以后使用:

class B {
    A<bool> & a_;
    public:
        B(A<bool> & a) : a_(a) { }

        void run() {
            printf("%s = %p\n", a_.name(), &a_);
        }
};

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM