在头文件中给定此类:
class ClassA
{
public:
ClassA(){};
}
然后在文件.cpp 中
#include file.h
ClassA* GlobalPointerToClassAType = new ClassA();
a。是否允许使用关键字"new"在文件范围的行中为堆(?(中的对象分配内存?
b。如果允许,那么构造函数ClassA((究竟是什么时候被调用的?
c。如果我改为写这行:,会有什么不同
ClassA GlobalInstanceOfClassAType = ClassA();
就调用构造函数的时间、内存效率和良好实践而言?
a。是否允许使用关键字"new"在文件范围的行中为堆(?(中的对象分配内存?
这是允许的。在这里使用new
是否是一种好的做法是基于意见的。我预测大多数人会回答否定。
b。如果允许,那么构造函数ClassA((究竟是什么时候被调用的?
让我们从一些概念开始。
在C++中,程序中的所有对象都有以下存储持续时间之一:
- 自动
- 静态的
- 线程(从C++11开始(
- 动态的
如果您检查cppreference,它会声明:
静态存储持续时间。对象的存储在程序开始时分配,在程序结束时解除分配。该对象只存在一个实例。在命名空间范围(包括全局命名空间(声明的所有对象都具有此存储持续时间,加上那些用static或extern声明的对象。有关初始化具有此存储持续时间的对象的详细信息,请参见非局部变量和静态局部变量。
因此,GlobalPointerToClassAType
具有静态存储持续时间,它符合";在命名空间范围(包括全局命名空间(声明的所有对象都具有此存储持续时间&";。
如果你深入了解以上部分的链接,你会发现:
在主函数开始执行之前,所有具有静态存储持续时间的非本地变量都会作为程序启动的一部分进行初始化(除非推迟,请参阅下文(。所有具有线程本地存储持续时间的非本地变量都将作为线程启动的一部分进行初始化,并在线程函数开始执行之前进行排序。对于这两类变量,初始化分为两个不同的阶段:
同一网站中有更多细节,如果你想了解更多,你可以深入了解,但对于这个问题,我们只关注初始化时间。根据引用,constructor ClassA()
可能在主函数开始执行之前被调用(除非延迟(。
什么是";延期";?答案在以下部分:
它是实现定义的,无论动态初始化发生在主函数的第一条语句之前(对于静态函数(还是线程的初始函数之前(对于线程局部函数(,还是推迟到之后。
如果非内联变量的初始化(由于C++17(被推迟到主/线程函数的第一条语句之后发生,则它发生在第一次odr使用任何变量之前,该变量的静态/线程存储持续时间定义在与要初始化的变量相同的转换单元中。如果给定的翻译单元中没有变量或函数被odr使用,那么在该翻译单元中定义的非局部变量可能永远不会被初始化(这为按需动态库的行为建模(。然而,只要使用了来自翻译单元的任何东西,所有初始化或破坏有副作用的非局部变量都将被初始化,即使它们没有在程序中使用。
让我们看一个来自godbolt的小例子。我使用clang,直接复制你的代码,除了Class A
和main
是在同一个翻译单元中定义的。您可以看到clang生成一些类似__cxx_global_var_init
的部分,其中调用了类ctor。