【发布时间】:2020-10-26 11:30:18
【问题描述】:
考虑basic.start.dynamic部分中的示例,即:
// - File 1 -
#include "a.h"
#include "b.h"
B b;
A::A(){
b.Use(); //#1
}
// - File 2 -
#include "a.h"
A a;
// - File 3 -
#include "a.h"
#include "b.h"
extern A a;
extern B b;
int main() {
a.Use(); //#2
b.Use();
}
下面的 cmets 是:
但是,如果 a 在 main 的第一条语句之后的某个时间点被初始化,则 b 将在其用于 A::A 之前被初始化。
我不明白为什么 b 在使用 A::A 之前会被保证初始化,而当 a 在 main 的第一条语句之后的某个时间点被初始化时。按照规定:
具有静态存储持续时间的非局部非内联变量的动态初始化是在main的第一条语句之前排序还是延迟,由实现定义。 如果它被延迟,它强烈发生在任何非初始化之前 - 使用与要初始化的变量在同一翻译单元中定义的任何非内联函数或非内联变量。
非初始化 odr-use 是 odr-use ([basic.def.odr]) 不是由非本地静态或线程存储持续时间变量的初始化直接或间接引起的 .
我能理解的是,当初始化被推迟时,变量a应该在变量a的odr-use(non-initialization odr-use)之前初始化,在标记的地方与#2。但是我无法理解的是,评论说 b 将在其用于 A::A 之前被初始化。 IIUC,函数A::A 的调用是变量a 初始化的一部分,因此变量b 在#1 的odr 使用不是非初始化odr 使用,因为它是由非局部静态或线程存储持续时间变量的初始化直接或间接引起。我认为它只能说变量b保证在#2之前被初始化,为什么评论说b将在其用于A之前被初始化::A ?如何解读这个例子?
【问题讨论】:
-
为什么会出现“非本地静态存储时长变量的初始化直接或间接引起的”异常呢?为了避免解决循环初始化问题?
-
@Peter-ReinstateMonica 我认为这句话是用来限制 odr-use 的情况,即什么样的 odr-use 可以触发这些被延迟的动态初始化的发生。回到我的问题,
b在#1的 odr 使用不是句子所说的例外,因此它不应该触发动态初始化的发生。但是评论说它触发了b的初始化,我只是不知道为什么这么说。 -
我们同意;我想知道这个限制被纳入标准的原因。
-
@cigien 好吧,我删除了
c++17标签。感谢您的建议。 -
@aschepler
A::A()的 odr-use 是由a在选择A::A()时的初始化直接引起的,因此导致b在A::A()内的 odr-use间接通过a的初始化。因为说明不延迟的情况的注释表明,即“特别是,如果 a 在进入 main 之前初始化,则不能保证 b 将在它被 a 的初始化 odr 使用之前被初始化,也就是说,在调用 A::A 之前。”
标签: c++ language-lawyer