C/C++中使用局部/全局变量初始值或默认值问题

 更新时间:2024年08月21日 10:23:29   作者:江北一滴水  
这篇文章主要介绍了C/C++中使用局部/全局变量初始值或默认值问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

在C语言中的全局变量和静态变量都是会自动初始化为0,堆和栈中的局部变量不会初始化而拥有不可预测的值。

C++保证了所有对象与对象成员都会初始化,但其中基本数据类型的初始化还得依赖于构造函数。

下文来详细探讨C风格的”默认初始化”行为,以及C++中成员变量的初始化规则。

一、初始化的语法

很多人至今不知道C++中如何正确地初始化一个变量,我们首先来解决语法的问题。

C语言中在声明时用=即可完成初始化操作。但我们偏向于使用C++风格(本文中均指面向对象程序设计风格)来初始化内置类型:

// C 风格
int i = 3;
int arr[] = {1, 2, 3}; 
// C++ 风格
int i(3);
int i = int(3);
int *p = new int(3);
int* arr = new int[3] {1, 2, 3};

在C语言中int a;表示声明了整型a但未初始化,而C++中的对象总是会被初始化的,无论是否写了圆括号或者是否写了参数列表,例如:

int basic_var;      // 未初始化:应用"默认初始化"机制
CPerson person;     // 初始化:以空的参数列表调用构造函数

二、默认初始化规则

定义基本数据类型变量(单个值、数组)的同时可以指定初始值,如果未指定C++会去执行默认初始化(default-initialization)。 那么什么是”默认初始化”呢?

  • 1.栈中的变量(函数体中的自动变量)和堆中的变量(动态内存)会保有不确定的值;
  • 2.全局变量和静态变量(包括局部静态变量)会初始化为零;
  • 3.(lanyan注)函数体中的自动变量在有些编译器下(我的是Clion2021.3),虽然在未初始化的情况下输出也是0,但是编译时会出现警告,所以这样写是不对的。

所以函数体中的变量定义是这样的规则:

//C++中
int i;                    // 不确定值
int i = int();            // 0
int *p = new int;         // 不确定值
int *p = new int();       // 0

三、静态和全局变量的初始化

未初始化的和初始化为零的静态/全局变量编译器是同样对待的,把它们存储在进程的BSS段(这是全零的一段内存空间)中。所以它们会被”默认初始化”为零。

来看例子:

int g_var;
int *g_pointer;
static int g_static;
 
int main(){
    int l_var;
    int *l_pointer;
    static int l_static;
 
    cout<<g_var<<endl<<g_pointer<<endl<<g_static<<endl;
    cout<<l_var<<endl<<l_pointer<<endl<<l_static<<endl;
};

输出:

0                   // 全局变量
0x0                 // 全局指针  
0                   // 全局静态变量
32767               // 局部变量
0x7fff510cfa68      // 局部指针
0                   // 局部静态变量

动态内存中的变量在上述代码中没有给出,它们和局部变量(自动变量)具有相同的”默认初始化”行为。

四、成员变量的初始化

成员变量分为成员对象和内置类型成员,其中成员对象总是会被初始化的。而我们要做的就是在构造函数中初始化其中的内置类型成员。

class A{
public:
    int v;
};
A g_var;
 
int main(){
    A l_var;
    static A l_static;
    cout<<g_var.v<<' '<<l_var.v<<' '<<l_static.v<<endl;
    return 0;
}

输出:

0 2407223 0

可见内置类型的成员变量的”默认初始化”行为取决于所在对象的存储类型,而存储类型对应的默认初始化规则是不变的。 所以为了避免不确定的初值,通常会在构造函数中初始化所有内置类型的成员。

Effective C++: Item 4一文讨论了如何正确地在构造函数中初始化数据成员。

这里就不展开了,直接给出一个正确的初始化写法:

class A{
public:
    int v;
    A(): v(0);
};

五、封闭类嵌套成员的初始化

再来探讨一下当对象聚合发生时成员变量的”默认初始化”行为,同样还是只关注于基本数据类型的成员。

class A{
public:
    int v;
};
 
class B{
public:
    int v;
    A a;
};
 
B g_var;
int main(){
    B l_var;
    cout<<g_var.v<<' '<<g_var.a.v<<endl;
    cout<<l_var.v<<' '<<l_var.a.v<<endl;
    return 0;
}

结果:

0 0
43224321 -1610612736

规则还是是一样的,默认初始化行为取决于它所属对象的存储类型。

封闭类(Enclosing)中成员对象的内置类型成员变量的”默认初始化”行为取决于当前封闭类对象的存储类型,而存储类型对应的默认初始化规则仍然是不变的。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C++容器适配器的概念与示例

    C++容器适配器的概念与示例

    C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量、链表、队列、栈,今天我们来探究一下stl容器适配器的使用吧
    2023-01-01
  • 深入理解C++编程中的局部变量和全局变量

    深入理解C++编程中的局部变量和全局变量

    这篇文章主要介绍了深入理解C++编程中的局部变量和全局变量,是C++入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • Linux中使用VS Code编译调试C++项目详解

    Linux中使用VS Code编译调试C++项目详解

    最近因为项目的需求,需要在Linux下开发C++相关项目,经过一番摸索最终实现了,下面这篇文章就给大家简单总结了一下如何通过VS Code进行编译调试的一些注意事项。有需要的朋友们可以参考借鉴,下面来跟着小编一起看看吧。
    2016-12-12
  • C/C++实现俄罗斯方块游戏

    C/C++实现俄罗斯方块游戏

    这篇文章主要介绍了如何利用C/C++实现经典游戏之一的俄罗斯方块,文中的实现步骤讲解详细,对我们学习C语言和C++有一定的帮助,需要的可以参考一下
    2022-02-02
  • C++中输出十六进制形式的字符串

    C++中输出十六进制形式的字符串

    这篇文章主要给大家介绍了C++中输出十六进制形式的字符串,文中给出了详细的介绍,有需要的朋友可以参考借鉴,下面来一起看看吧。
    2016-12-12
  • C++类和对象深入探索之分文件编写点和圆的关系详解

    C++类和对象深入探索之分文件编写点和圆的关系详解

    先前把C++类和对象的封装讲完了,并且留下了一个判断两个立方体是否相等的案例,但是那么多知识点,仅仅一个案例是不够的,所以再来一个分文件编写点圆关系的案例;创建圆类和点类,圆类包含点类,算是一个嵌套吧,顺便复习一下分文件编写的方法,开整
    2022-05-05
  • OpenCV实现更改图片颜色功能

    OpenCV实现更改图片颜色功能

    这篇文章主要为大家详细介绍了如何利用OpenCV实现更改图片颜色的功能,文中代码介绍详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-05-05
  • C++运算符重载的方法详细解析

    C++运算符重载的方法详细解析

    运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的
    2013-10-10
  • Qt采用线程以队列方式实现下发数据

    Qt采用线程以队列方式实现下发数据

    在C++中队列是一种常用的数据结构之一,一种特殊的线性表,一般采用先进先出的方式。本文主要为大家介绍了Qt如何以队列方式实现下发数据,感兴趣的可以了解一下
    2022-10-10
  • C++程序函数的重载和函数模板示例代码

    C++程序函数的重载和函数模板示例代码

    C++允许在同一作用域中用同一函数名定义多个函数,这些函数的参数个数和参数类型不相同,这些同名的函数用来实现不同的功能,这就是函数的重载,这篇文章主要介绍了C++程序函数的重载和函数模板,需要的朋友可以参考下
    2024-03-03

最新评论