C ++中是否存在未初始化的对象?

时间:2017-09-26 13:19:34

标签: c++ initialization

如果所有对象都至少有一个构造函数,则默认情况下由编译器或用户定义,然后如何对象未初始化。

2 个答案:

答案 0 :(得分:15)

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

此类对象可以通过 default-intialization 创建。 这在c ++标准中有说明,(第11.6节初始化器)[dlc.init]:

  

默认初始化 T类型的对象意味着:

     

(7.1) - 如果T是(可能是cv限定的)类类型(第12条),则考虑构造函数。适用   枚举构造函数(16.3.1.3),通过重载选择初始化程序()的最佳构造函数   决议(16.3)。这样选择的构造函数用空参数列表调用,以初始化   对象

     

(7.2) - 如果T是数组类型,则每个元素都是默认初始化的。

     

(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]可能会有所帮助:

  

在非委托构造函数中,如果给定的可能构造的子对象未由mem-指定   initializer-id(包括没有mem-initializer-list的情况,因为构造函数没有   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) - 否则,实体默认初始化(11.6)

一个简单的匿名联盟的成员也可能没有被初始化。

也可以询问是否可以在没有任何初始化的情况下开始对象生命周期,例如使用reinterpret_cast。答案是reinterpret_cast creating a trivially default-constructible object

答案 1 :(得分:1)

标准没有讨论对象的存在,但是,有一个生命周期对象的概念。

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

  

类型为T的对象的生命周期始于:

     
      
  • 获取具有T类型的正确对齐和大小的存储,

  •   
  • 如果对象具有非空的初始化,则其初始化完成

  •   

非空初始化定义为

  

如果一个对象属于一个类或aggregate type,并且它或其一个子对象是由trivial default constructor以外的构造函数初始化的,则称该对象具有非空的初始化。

我们可以得出结论,对于具有空初始化的对象(例如int s),他们的生命周期在获取存储后立即开始,即使它们未被初始化。

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

†​​为了便于阅读而添加链接,它们没有出现在标准中