C 中存在非初始化的对象

Do uninitialized objects exist in C++?

本文关键字:对象 初始化 存在      更新时间:2023-10-16

如果所有对象至少具有一个构造函数,则默认是由编译器或用户定义的默认c'tor。

可以声明对对象进行不执行初始化。这些对象确实存在,它们具有不确定的值,并且使用此值是未定义的行为(该规则对字符有例外)。

可以通过 default-intialization 创建此类对象。这在C 标准(§11.6初始化器)[dlc.init]中说明了:

to default-initialize 类型的对象表示:

(7.1) - 如果t是(可能是CV值的)类类型(第12条),则考虑构造函数。适用 列举构造函数(16.3.1.3),并且通过超载选择了 initializer ()的最佳构造函数 决议(16.3)。因此,选择的构造函数被称为空的参数列表,以初始化 对象。

(7.2) - 如果t是数组类型,则每个元素被默认为initialized。

(7.3) - 否则,未执行初始化。

尽管如此,静态对象始终是零键的

int i; //zero-initialized
struct A{
  int i;
  };
struct B
  {
  B(){};
   B(int i)
    :i{i}{}
  int i;
  int j;
  };
A a; //a.i is zero-initialized
int main()
  {
   int j;             //not initialized
   int k{};           //zero-initialized
   A b;               //b.i not initialized
   int* p = new int;  //*p not initialized
   A*   q = new A;    //q->i not initialized
   B ab;              //ab.i and ab.j not initialized
   B ab2{1};          //ab.j not initialized
   int xx[10];        //xx's element not initialized.
   int l = i;    //OK l==0;
   int m = j;    //undefined behavior (because j is not initialized)
   int n = b.i;  //undefined behavior 
   int o = *p; //undefined behavior 
   int w = q->i; //undefined behavior 
   int ex = x[0] //undefined behavior
   }

对于成员初始化[class.base.init]可能会有所帮助:

在非级别的构造函数中 initializer-id(包括没有mem-Initializer列表的情况,因为构造函数没有 ctor-Initializer),然后 - 如果该实体是具有默认成员初始化器(12.2)和

的非静态数据成员

(9.1.1) - 构造师的班级是工会(12.3),该工会的其他变体成员没有指定 由mem-initializer-id或

(9.1.2) - 构造人的班级不是工会,如果实体是匿名联盟的成员,则没有 该工会的其他成员是由Mem-Initializer-ID指定的, 该实体是根据11.6中指定的默认成员初始化器初始化的。

(9.2) - 否则,如果实体是匿名联盟或变体成员(12.3.1),则没有初始化是 执行;

(9.3) - 否则,实体被默认为initialization(11.6)

微不足道的匿名联盟的成员也可能不会初始化。


还可以通过使用reinterpret_cast来询问对象寿命是否可以开始而无需任何初始化,以示出。答案是 no :reinterpret_cast创建一个琐碎的默认构造对象

标准不谈论对象的存在,但是,对象有一个 lifetimes 的概念。

具体来说,来自[basic.life]

类型T对象的寿命开始:

  • 获得了适当的对齐和大小T的存储,并且

  • 如果对象的初始化不变,则其初始化已完成

非胶合初始化定义为

如果对象是类型或聚合类型的对象,则具有非胶合初始化,并且它或其一个子对象之一是由构造函数初始化的。

我们可以得出结论,对于具有空置初始化的对象(例如int s),他们的寿命在获取存储后立即开始,即使将它们保持不可原始化。

void foo()
{
    int i;  // i's lifetime begins after this line, but i is uninitialized
    // ...
}

†链接添加以易于阅读,它们不会出现在标准

使用字节数组:

alignas(alignof(Mat4)) uint8_t result[sizeof(Mat4)];
// ..
node->updateMatrix( ..., /*result*/ reinterprect_cast<Mat4*>(&result[0])); 

Mat4的构造函数不会触发。