C/C++变量的自动初始化——重要

对于内置变量的自动初始化

代码1:

#include<stdio.h>
#define CONST 100
int *p1;
int a[2];
int b;
static int c;
main()
{
    int d;
    static int e;
    int f[2];
    int *p2;
    printf("CONST=%d\n",CONST);
    printf("a[0]=%d\n",a[0]);
    //printf("*p1=%d\n",*p1);
    printf("b=%d\n",b);
    printf("c=%d\n",c);
    printf("d=%d\n",d);
    printf("e=%d\n",e);
    printf("f[0]=%d\n",f[0]);
    printf("*p2=%d\n",*p2);
}

按 Ctrl+C 复制代码

输出:

CONST=100

a[0]=0

b=0

c=0

d=2514932

e=0

f[0]=1307813

*p2=457819009

数据区存放已初始化的全局变量,静态变量(包括全局和局部的),常量。

未初始化数据区(uninitializeddata segment,BSS)存放全局未初始化的变量。BSS的数据在程序开始执行之前被初始化为0或NULL。BSS段的变量在目标文件中只占一个符号位,编译器并没有给变量分配空间,所谓的“初始化为0”是指要链接阶段才申请了空间,并随即初始化为0。而已初始化的全局变量要在占用目标文件的大小的。

换句话说全局变量,静态变量(包括全局和局部的),常量未显式初始化被默认地初始化时0或NULL。

如果试图打印*p1则会发生段错误,因为p1指向的是一个NULL地址。

而局部的非静态变量未显式初始化时是一个随机的数,一般是个很大的数。

对于类类型变量的自动初始化

不论是在全局还是局部作用域,类类型变量都会调用“默认构造函数”进行初始化。

所谓“默认构造函数”就是指空参数的构造函数。

代码2:

class A{
public:
    int value;
    A(){
        cout<<"Intitialize A"<<endl;
        value=3;
    }
};

A a1;

int main(){
    A a2;
    cout<<a1.value<<endl;
    cout<<a2.value<<endl;
    return 0;
}

输出:

Intitialize A
Intitialize A
3
3

如果类没有显式地定义任何构造函数,则编译器会自动为其生成空参数的构造函数,称为“合成默认构造函数”。“合成默认构造函数”初始化成员的规则有3条:

1.对象在全局作用域或为静态局部对象时,则类的内置成员变量被初始化为0.

2.对象在局部作用域定义时,则类的内置成员变量不被初始化为0.

代码3:

class A{
public:
    int value;
};

A a1;

int main(){
    A a2;
    static A a3;
    cout<<a1.value<<endl;
    cout<<a2.value<<endl;
    cout<<a3.value<<endl;
    return 0;
}

输出:

0
2510836
0

3.对于类类型成员按照其自身的(合成)默认构造函数进行初始化。——重要

代码4:

class A{
public:
    int value;
    A(){
        value=5;
    }
};

class B{
public:
    int value;
    A a;
};

B b1;

int main(){
    B b2;
    cout<<b1.value<<"\t"<<b1.a.value<<endl;
    cout<<b2.value<<"\t"<<b2.a.value<<endl;
    return 0;
}

输出:

0     5
134514784     5

代码5:

class A{
public:
    int value;
};

class B{
public:
    int value;
    A a;
};

B b1;

int main(){
    B b2;
    cout<<b1.value<<"\t"<<b1.a.value<<endl;
    cout<<b2.value<<"\t"<<b2.a.value<<endl;
    return 0;
}

输出:

0   0
134514736   -1081710584

如果类显式提供了带参数的构造函数,则编译器不会再为其生成空参数的构造函数。这时候就不能用空参数来定义类类型变量。下面的代码是错误的:

class A{
public:
    int value;
    A (int i):value(i){}
};

class B{
public:
    int value;
    A a;//调用的是空参数的构造函数
};

int main(){
    A a;
    return 0;
}

转自:http://www.cnblogs.com/zhangchaoyang/articles/2671551.html

时间: 2024-10-12 21:42:40

C/C++变量的自动初始化——重要的相关文章

c++ 变量定义 的初始化规则

当定义没有初始化式的变量(如int i;)时,系统有可能会为我们进行隐式的初始化.至于系统是否帮我们隐式初始化变量,以及为变量赋予一个怎样的初始值,这要取决于该变量的类型以及我们在何处定义的该变量.            1]内置类型变量的初始化           内置变量是否自动初始化,取决于该变量定义的位置.           ①在全局范围内的内置类型变量均被编译器自动初始化为0值 1 #include<iostream> 2 3 using namespace std; 4 5 //

C++变量的默认初始化规则

定义没有初始化式的变量时,系统有时候会帮我们初始化变量.系统如何初始化取决于变量的类型以及变量定义的位置. 内置类型变量是否自动初始化取决于变量定义的位置.函数体外定义的变量初始成0:函数体内定义的变量不进行自动初始化.除了用作赋值操作的左操作数,其他任何使用未初始化变量的行为都是未定义的,不要依赖未定义行为. 以int类型为例,一段简单的测试代码: #include <iostream> using namespace std; int a; int main() { int b; cout

C++中变量自动初始化的问题

C++中有一些变量在如果没有赋初值会被编译器自动赋值为0,但有的变量又不会这样,而得到一个随机数,下面具体讨论一下: 首先看一下C++中的几个存储区:1.栈区:由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈.     2.堆区:一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 .注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵.     3.全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变

.NET中那些所谓的新语法之一:自动属性、隐式类型、命名参数与自动初始化器

开篇:在日常的.NET开发学习中,我们往往会接触到一些较新的语法,它们相对以前的老语法相比,做了很多的改进,简化了很多繁杂的代码格式,也大大减少了我们这些菜鸟码农的代码量.但是,在开心欢乐之余,我们也不禁地对编译器内部到底为我们做了哪些事儿而感到好奇?于是,我们就借助反编译神器,去看看编译器到底做了啥事!其实本篇中很多都不算新语法,对于很多人来说可能都是接触了很久了,这里主要是针对.NET的老版本来说,是一个“相对”的新语法. /* 新语法索引 */ 1.自动属性 Auto-Implemente

Delphi结构体的扩展,可以自动初始化,反初始化,自定义拷贝函数.

转载:http://www.raysoftware.cn/?p=518&utm_source=tuicool 恭贺Delphi XE7诞生,Delphi XE7在编译器内部集成了我之前所实现的动态数组扩展.http://www.raysoftware.cn/?p=278现在有一个更悠久的历史需求,在QC的Delphi板块上置顶了好多年.官方一直没有实现.http://qc.embarcadero.com/wc/qcmain.aspx?d=21729众所周知Delphi的record和CPP的st

GoLang学习之变量定义和初始化

变量命名原则 go语言的变量名有字母数字和下划线组成,首字母不能为数字,但是字母不仅仅只限于英文字母,所有的UTF-8字符都是可以的. 变量声明和初始化方式 使用var关键字 var a int = 9 var str string ="jisuanji" 注意,Go语言变量类型放在变量名之后! 如果上面的代码段没有初始化值,那么变量就会被初始化为对应类型的零值. var a int 这个代码片段声明了一个int类型变量a,并把a初始化为int零值,即0. 忽略类型 这种声明和初始化变

Java初始化顺序(静态变量、静态初始化块、实例变量、实例初始化块、构造方法)

1.执行顺序 1.1.一个类中的初始化顺序 (静态变量.静态初始化块)=>(变量.初始化块.构造器). 1.2.两个具有继承关系类的初始化顺序 父类的(静态变量.静态初始化块)=> 子类的(静态变量.静态初始化块)=> 父类的(变量.初始化块.构造器)=> 子类的(变量.初始化块.构造器). 示例如下:(结果见注释) 1 class A { 2 public A() { 3 System.out.println("Constructor A."); 4 } 5

自己实现简单的AOP(四)自动初始化代理对象

前面三篇随笔,已经完成了AOP的核心功能,但 代理对象的初始化还是有些麻烦,本文将解决该问题. Demo 片段如下: public class HomeController : Controller { /// <summary> /// 使用 Autowired Attribute 自动初始化代理对象 /// </summary> [Autowired] public Service myService { get; set; } public ActionResult Inde

Java类的初始化顺序 (静态变量、静态初始化块、变量、初始化块、构造器)(转)

大家在去参加面试的时候,经常会遇到这样的考题:给你两个类的代码,它们之间是继承的关系,每个类里只有构造器方法和一些变量,构造器里可能还有一段代码对变量值进行了某种运算,另外还有一些将变量值输出到控制台的代码,然后让我们判断输出的结果.这实际上是在考查我们对于继承情况下类的初始化顺序的了解. 我们大家都知道,对于静态变量.静态初始化块.变量.初始化块.构造器,它们的初始化顺序以此是(静态变量.静态初始化块)>(变量.初始化块)>构造器.我们也可以通过下面的测试代码来验证这一点: Java代码 p