为什么调用成员函数不调用该对象的ODR-USE? [英] Why doesn't calling member function invoke the ODR-USE of that object?

查看:252
本文介绍了为什么调用成员函数不调用该对象的ODR-USE?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

cppref 中说,

如果将非内联变量的初始化(自C ++ 17起)推迟在main/thread函数的第一条语句之后进行,则它在任何函数的第一次odr-use之前发生具有与待初始化变量相同的转换单元中定义的静态/线程存储持续时间的变量.

If the initialization of a non-inline variable (since C++17) is deferred to happen after the first statement of main/thread function, it happens before the first odr-use of any variable with static/thread storage duration defined in the same translation unit as the variable to be initialized.

然后提供了延迟动态初始化的示例:

And later it gives an example of deferred dynamic initialization:

// - File 1 -
#include "a.h"
#include "b.h"
B b;
A::A(){ b.Use(); }

// - 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();
  b.Use();
}

评论说:

如果amain 的第一条语句之后的某个时刻初始化(odd使用File 1中定义的函数,强制其动态初始化运行),则b将在A :: A

If a is initialized at some point after the first statement of main (which odr-uses a function defined in File 1, forcing its dynamic initialization to run), then b will be initialized prior to its use in A::A

为什么会出现 if 情况? a.Use()不能在a之前使用a来初始化a吗?

Why can the if situation happen? Doesn't a.Use() odr-use a thus a must be initialized before this statement?

推荐答案

简而言之,为什么要麻烦ab的初始化顺序?

In short, why bother the order of initialization of a and b?

该示例未显示任何内容,表明a 应该必须在b之前初始化,以使程序定义良好.

The example shows nothing that indicates a should be necessarily initialized before b to make the program well-defined.

  • extern A a;确实在extern B b;之前,但这与顺序无关.

  • It is true that extern A a; is before extern B b;, but this is nothing to do with the order.

在从文件3转换的TU的main函数中,在a.Use();中的评估先于在b.Use();中的评估是顺序的,但这仍然与顺序无关. /p>

It is also true that evaluation in a.Use(); is sequenced before evaluation in b.Use(); in the main function in the TU translated from File 3, but this is still nothing to do with the order.

要明确定义a.Use()与此特定顺序无关,除非存在其他依赖性(例如,子对象初始化暗含顺序).

Making a.Use() to be well-defined has nothing to do with this particular order, unless there are other dependencies (e.g. subobject initialization implies order).

OTOH,如果您要附加订单,该如何指定?

OTOH, if you want the additional order, how do you specify it?

附件:

措辞在主/线程函数的第一条语句之后发生"很奇怪.似乎有意的是在主/线程函数的第一条语句之前没有发生",并且编辑器有时会漏掉在单个语句的求值过程中可能有不止一个适用于二进制关系的求值.这源自标准,但已通过

The wording "happen after the first statement of main/thread function" is strange. It seems that the intentional one is "does not happen before the first statement of main/thread function", and the editor occasionally missed there can be more than one evaluations applicable to the binary relationship in evaluation of a single statement. This originates from the standard, but it has been corrected by P0250R3.

实际上,我发现示例来自标准,引用自N4727 [basic.start.dynamic]/4:

Actually, I find the example comes from the standard, quoted from N4727 [basic.start.dynamic]/4:

3 非初始化odr-use 是odr-use(6.2),并非由初始化a导致直接或间接引起的 非本地静态或线程存储持续时间变量.

3 A non-initialization odr-use is an odr-use (6.2) not caused directly or indirectly by the initialization of a non-local static or thread storage duration variable.

4是否动态初始化带有静态变量的非局部非内联变量是实现定义的 存储持续时间在main的第一条语句之前排序或被延迟.如果推迟,则强烈 发生在任何非初始化odr使用任何非内联函数或非内联变量中定义的事件之前 与要初始化的变量相同的转换单元.55由实现定义,其中线程和 在程序中的哪一点发生这种延迟的动态初始化. [注意:这些要点应该是 选择这种方式可以使程序员避免死锁. —尾注] [示例:

4 It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration is sequenced before the first statement of main or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized.55 It is implementation-defined in which threads and at which points in the program such deferred dynamic initialization occurs. [ Note: Such points should be chosen in a way that allows the programmer to avoid deadlocks. —end note ] [ Example:

// - File 1 -
#include "a.h"
#include "b.h"
B b;
A::A(){
    b.Use();
}

// - 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();
    b.Use();
}

由实现定义是否在输入main之前初始化ab还是 初始化被延迟,直到第一次在main中使用a为止.特别是,如果amain被初始化之前被初始化 输入的内容,不能保证b会在a的初始化之前被初始化之前被初始化,即, 在A::A被调用之前.但是,如果amain的第一条语句之后的某个时刻被初始化,则b将是 在A::A中使用之前进行了初始化. —完示例]

It is implementation-defined whether either a or b is initialized before main is entered or whether the initializations are delayed until a is first odr-used in main. In particular, if a is initialized before main is entered, it is not guaranteed that b will be initialized before it is odr-used by the initialization of a, that is, before A::A is called. If, however, a is initialized at some point after the first statement of main, b will be initialized prior to its use in A::A. —end example ]

55)在这种情况下,将初始化具有静态存储持续时间且具有副作用初始化的非局部变量,即使它是 本身不被滥用(6.2,6.6.4.1).

55) A non-local variable with static storage duration having initialization with side effects is initialized in this case, even if it is not itself odr-used (6.2, 6.6.4.1).

这篇关于为什么调用成员函数不调用该对象的ODR-USE?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆