在文件范围内使用关键字 'new'?

Using the keyword 'new' in file scope?

给定头文件中的 class:

class ClassA
{
public:
ClassA(){};
}

然后在file.cpp

#include file.h
ClassA* GlobalPointerToClassAType = new ClassA();

一个。是否允许使用关键字 'new' 以文件范围的行为堆中的对象分配内存(?)是否是一种好习惯?

b。如果允许,那么构造函数 ClassA() 实际调用的确切时间是什么时候?

c。如果我改写这一行,它有什么不同:

ClassA GlobalInstanceOfClassAType = ClassA();

在调用构造函数的时间、内存效率和良好实践方面?

a. Is it allowed, and is it good practice to use the keyword 'new' to allocate memory for an object in the heap(?) in lines of file-scope?

这是允许的。在这里使用 new 是否是好的做法是基于意见。而且我预测大多数人会回答不。


b. If it is allowed, then when exactly does the constructor ClassA() is actually called?

让我们从一些概念开始。

在 C++ 中,程序中的所有对象都具有以下存储持续时间之一:

  • 自动
  • 静态
  • 线程 (C++11 起)
  • 动态

如果您检查 cppreference,它声称:

static storage duration. The storage for the object is allocated when the program begins and deallocated when the program ends. Only one instance of the object exists. All objects declared at namespace scope (including global namespace) have this storage duration, plus those declared with static or extern. See Non-local variables and Static local variables for details on initialization of objects with this storage duration.

因此,GlobalPointerToClassAType 具有静态存储持续时间,它符合“在命名空间范围(包括全局命名空间)声明的所有对象都具有此存储持续时间...”的声明。

如果你深入了解上面部分的link,你会发现:

All non-local variables with static storage duration are initialized as part of program startup, before the execution of the main function begins (unless deferred, see below). All non-local variables with thread-local storage duration are initialized as part of thread launch, sequenced-before the execution of the thread function begins. For both of these classes of variables, initialization occurs in two distinct stages:

同一个站点中有更多的细节,如果你想了解更多可以更深入,但是对于这个问题,我们只关注初始化时间。根据参考资料,constructor ClassA() 可能会在主函数开始执行之前被调用(除非延迟)。

什么是“延迟”?答案在下面sections:

It is implementation-defined whether dynamic initialization happens-before the first statement of the main function (for statics) or the initial function of the thread (for thread-locals), or deferred to happen after.

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. If no variable or function is odr-used from a given translation unit, the non-local variables defined in that translation unit may never be initialized (this models the behavior of an on-demand dynamic library). However, as long as anything from a translation unit is odr-used, all non-local variables whose initialization or destruction has side effects will be initialized even if they are not used in the program.

让我们看一个来自 godbolt 的小例子。我用的是clang,直接copy你的代码,只是Class Amain定义在同一个翻译单元。您可以看到 clang 生成了一些像 __cxx_global_var_init 这样的部分,其中调用了 class ctor。