默认情况下如何初始化局部变量和全局变量?

时间:2010-08-24 04:24:12

标签: c++ initialization

根据以下情况,我是对的吗?

  • global_A引用初始化为null。
  • global_int为0
  • local_A引用为空
  • local_int未初始化
  • global_A.x和local_A.x都未初始化。

感谢任何帮助。


A global_A;
int global_int;

class A {
  public : int x;
}

int main()
{
  int local_int;
  A local_A;
}

10 个答案:

答案 0 :(得分:13)

建立安德烈的回应。

$ 3.6.2-“具有静态存储持续时间(3.7.1)的对象应在进行任何其他初始化之前进行零初始化(8.5)。”在OP中,“global_A”和“global_int”具有静态存储持续时间。 “local_int”和“local_A”没有链接,因为它们是本地对象。

$ 8.5 / 5-零初始化T类型的对象意味着:

  

- 如果T是标量类型(3.9),则   object被设置为0(零)的值   转换为T;

     

- 如果T是非联合类类型,则各自   非静态数据成员和每个   基类子对象是   zeroinitialized;

     

- 如果T是联合类型,则为对象   第一个命名数据成员89)是   零初始化;

     

- 如果T是数组类型,则每个元素   是零初始化;

     

- 如果T是引用类型,则不   执行初始化。

$ 6.7.4 / 4-“具有静态存储持续时间(3.7.1)的所有本地对象的零初始化(8.5)在任何其他初始化发生之前执行。具有静态的POD类型(3.9)的本地对象使用常量表达式初始化的存储持续时间在首次输入块之前初始化。允许执行 在允许实现静态初始化具有命名空间范围内的静态存储持续时间的对象的相同条件下,使用静态存储持续时间对其他本地对象进行早期初始化(3.6.2)。否则,在第一次控制通过其声明时初始化这样的对象;这样的对象在初始化完成时被认为是初始化的。如果通过抛出异常退出初始化,则初始化未完成,因此下次控制进入声明时将再次尝试初始化。如果控件在初始化对象时重新输入声明(递归),则行为未定义。“

编辑2:

  

$ 8.5 / 9-“如果没有初始化程序   为对象指定的,以及   对象是(可能是cv合格的)   非POD类类型(或其数组),   对象应该是   默认初始化;如果对象是   const限定类型,   基础类型应具有   用户声明的默认构造函数。    否则,如果没有为非静态对象指定初始值设定项,则为   对象及其子对象(如果有)   有一个不确定的首字母   value90) ;如果对象或任何   它的子对象是const限定的   类型,该程序是不正确的。“

一般情况下,您希望阅读这些部分以及8.5美元,以便在这方面保持良好状态。

答案 1 :(得分:7)

您的代码中没有引用,因此您提及“引用”的任何一点都没有意义。

在您的示例中,全局对象 - global_intglobal_A - 都是零初始化的。两个本地对象 - local_intlocal_A - 都包含不确定的值,这意味着local_intlocal_A.x未初始化。

P.S。当然,正如其他已经指出的那样,您的代码是不可编译的。在声明A之前,您无法声明class A个对象(并且在类定义后缺少;)。

答案 2 :(得分:7)

基本上,每当你声明一个变量时,编译器都会调用它的默认构造函数,除非你另有说明。

语言级别类型(例如指针,'int','float','bool'等)“默认构造函数”什么都不做,它只是在声明时保留内存(全局/静态变量)是特殊情况,有关详细信息,请参阅chubsdad's answer。这意味着它们几乎可以是任何东西,因为你通常无法确定之前的内存中是什么,甚至是内存来自哪里(除非是'placement new'运算符)。

您创建的类没有构造函数,因此编译器将为您生成一个默认构造函数,它只调用每个成员/变量的构造函数。如果你包含前一段中提供的信息,你可以看到变量'x'将调用它的默认构造函数,它什么都不做,因此没有初始化为任何值。

正如其他人所说,你的代码或指针中没有引用,因此术语“NULL”在这里的所有情况下都是无效的。 NULL通常是指一个指针,它像其他语言级别类型一样,在为它赋值之前不会被设置为任何值(除非它当然是一个全局/静态变量)。

答案 3 :(得分:3)

如果您有参考文献,那么只是为了完整起见:

必须在声明时初始化引用,否则您将受到编译器错误的惩罚。这意味着引用总是需要它引用的另一个值或引用(如说),这是由编译器确保的,所以你不能忘记它。这也意味着引用永远不能是空指针。但是,他们引用的对象可能无效。

答案 4 :(得分:1)

global_A和local_A不是引用;它们是对象,使用默认构造函数创建。默认构造函数尚未指定,因此将生成它,它将不执行任何操作,因此成员变量将保持未初始化。

答案 5 :(得分:1)

A global_A;

这是一个实例,而不是一个指针,你的程序在进入main之前会调用构造函数。

要获取指向实例的指针而不是必须编写的实例:

A* global_A;

global_int初始化为0,因为所有全局变量都初始化为默认值。

每当程序进入通过调用其构造函数声明它的函数时,变量A local_A将被初始化。

和以前一样,如果你想要一个指向A的指针,你必须编写A * local_A,但这次你必须自己将它初始化为NULL。

A *local_A = NULL;

变量local_int不会被初始化,因为它是原始类型。

如果初始化local_A.x取决于A的构造函数,则默认构造函数不会初始化local_A.x.如果x创建A实例的类实例将使用其类的构造函数初始化x。

答案 6 :(得分:-2)

它们都需要初始化。编译器会给你一个警告。

答案 7 :(得分:-2)

除非您转发声明A。

,否则此代码将无法编译

global_A引用初始化为null - 不,它将引用A对象。 global_int为0 - 想想,需要检查。 local_A引用为null - 否,与global_A相同。 local_int未初始化 - 是的,它会获得一些垃圾值。 global_A.x和local_A.x都未初始化 - 是。

您可以随时调试和查看。

答案 8 :(得分:-2)

好吧,伙计们......我更加困惑,因为我看到来自这里的回复。无论如何,我做了如下所示的测试:

1 #include

  2 using namespace std;
  3 
  4 class A {
  5 
  6 public :
  7         A() : x(9) {};
  8         int x;
  9 
 10 };
 11 
 12 A global_a;
 13 int global_b;
 14 
 15 int main() {
 16 
 17         A local_a;
 18         int local_b;
 19         cout << "global_a.x = " << global_a.x << '\n';
 20         cout << "local_a.x = " << local_a.x << '\n';
 21 
 22         cout << "global_b = " << global_b << '\n';
 23         cout << "local_b = " << local_b << '\n';
 24 
 25 }

在ubuntu linux上使用我的g ++编译器的结果:

global_a.x = 9

local_a.x = 9

global_b = 0

local_b = 0

我认为local_b应该是未定义的,但不知何故编译器默认初始化它。但是local_a ..我不确定是否应该默认初始化。从这里的测试.. local_a似乎被初始化。不确定这是否符合标准c ++规范(例如,C ++ PRimer第4版表示无论在何处声明类变量,都使用默认构造函数 - 这是否意味着类型的变量是初始化的,无论是全局变量还是本地变量?)。

无论是什么......这是一个混乱的大地狱。也许我应该放弃学习C ++。 Java更直接。见鬼啊!

答案 9 :(得分:-3)

  

global_A引用初始化为   空。

不,它是一个有效的对象(基于默认构造函数构建,您的代码中没有,但编译器会添加它)

  

global_int为0

  

local_A引用为空

不,与全球

相同的原因
  

local_int未初始化

不,它初始化为0

  

global_A.x和local_A.x都是   初始化。

两者都没有被初始化为0