为什么调用成员函数不调用该对象的ODR-USE? [英] Why doesn't calling member function invoke the ODR-USE of that object?
问题描述
在 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();
}
评论说:
如果
a
在main
的第一条语句之后的某个时刻初始化(odd使用File 1
中定义的函数,强制其动态初始化运行),则b
将在A :: A
If
a
is initialized at some point after the first statement ofmain
(which odr-uses a function defined inFile 1
, forcing its dynamic initialization to run), thenb
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?
推荐答案
简而言之,为什么要麻烦a
和b
的初始化顺序?
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 beforeextern 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
之前初始化a
或b
还是 初始化被延迟,直到第一次在main
中使用a
为止.特别是,如果a
在main
被初始化之前被初始化 输入的内容,不能保证b
会在a
的初始化之前被初始化之前被初始化,即, 在A::A
被调用之前.但是,如果a
在main
的第一条语句之后的某个时刻被初始化,则b
将是 在A::A
中使用之前进行了初始化. —完示例]
It is implementation-defined whether either
a
orb
is initialized beforemain
is entered or whether the initializations are delayed untila
is first odr-used inmain
. In particular, ifa
is initialized beforemain
is entered, it is not guaranteed thatb
will be initialized before it is odr-used by the initialization ofa
, that is, beforeA::A
is called. If, however,a
is initialized at some point after the first statement ofmain
,b
will be initialized prior to its use inA::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屋!