C++ 初始化的坑,你也遇到过吗?

新闻 前端
谈及 C++ 的初始化,我们都知道要在变量定义的时候给它赋初值。确实,在每次定义的时候就初始化不仅可以避免脏数据产生,还能增加代码的可读性。

 谈及 C++ 的初始化,我们都知道要在变量定义的时候给它赋初值。确实,在每次定义的时候就初始化不仅可以避免脏数据产生,还能增加代码的可读性。但是,你知道这其中有多少陷阱吗?

[[345626]]

陷阱1:默认初始化的坑

请看一下代码,你能知道哪些变量的值是确定的?

  1. int a; 
  2.  
  3. void func() 
  4.  
  5.  
  6. int b; 
  7.  
  8. static int c; 
  9.  
  10. cout<<"a: "<<a<<", b :"<<b<<", c :"<<c<<endl; 
  11.  
  12.  
  13. int main() 
  14.  
  15.  
  16. cout<<"main a: "<<a<<endl; 
  17.  
  18. func(); 
  19.  
  20. return 0
  21.  

打印结果是:

  1. main a: 0 
  2.  
  3. a: 0, b :32694, c :0 

可以看到,三个变量都没有显式初始化,但a,c都被赋予了默认值,而b是不确定的值。

其实我们可以从《C++Primer》中找到答案:“定义于任何函数体之外的变量被初始化为0,定义于函数体内部的内置类型变量将不被初始化”。所谓定义于函数体之外的变量,其实就是全局变量,这里拓展说一下:

初始化过的全局变量,由编译器将其保存于静态存储区的data段,并且这样的值越多,程序就越大,操作系统会在程序启动时,将全局变量的值复制到data段中,即完成变量的初始化。

未初始化的全局变量,由编译器保存于静态存储区的bss段,并且这样的值不会被使程序变大,操作系统加载程序时才分配相应的内存,并将bass段清0,即完成变量的初始化。

所以,定义在函数体之外的变量,会被赋默认值。

但定义在函数中的变量,是在栈中分配的内存,属于动态存储区,此区操作系统不会帮助你清0,所以此处定义的值都是未定义的。

陷阱2:数组初始化的坑

  1. int buff[10] = {0}; 
  2.  
  3. for(int i = 0;i<10;i++) 
  4.  
  5.  
  6. cout<<buff[i]<<endl; 
  7.  

这段代码相信大家平时常写,答案很明显,都是0,但实际的原因,真的是因为{0}代表要将每个值设为0吗?

答案是否定的,请看下面的这段代码:

  1. int buff_2[10] = {1}; 
  2.  
  3. for(int i = 0;i<10;i++) 
  4.  
  5.  
  6. cout<<buff_2[i]<<","
  7.  

得到的答案是:1,0,0,0,0,0,0,0,0,0,大家注意到了吗?只有第一个值才是1,后面的全是0!

所以,这个坑其实是C++初始化列表的坑,初始化列表的定义中说明,如果初始化列表的数量比定义的数量少,那么未被定义到的值将会被赋予默认值!

陷阱3:memset的坑

  1. char buff[10]; 
  2.  
  3. memset(buff,0,sizeof(buff)); 
  4.  
  5. for(int i = 0;i<10;i++) 
  6.  
  7.  
  8. printf("%d ",buff[i]); 
  9.  

大家一定会觉得这段代码很简单,没错,打印结果就是都为0,的确很简单,但是,看下接下来的代码:

  1. int buff_2[10]; 
  2.  
  3. memset(buff_2,1,sizeof(buff_2)); 
  4.  
  5. for(int i = 0;i<10;i++) 
  6.  
  7.  
  8. printf("%d ",buff_2[i]); 
  9.  

是的,变量的类型变了,打印的结果是:

  1. 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 

是不是觉得很奇怪,接下来,我们把这句:

  1. printf("%d ",buff_2[i]); 

改为:

  1. printf("0X%x ",buff_2[i]); 

得到的结果是:

  1. 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 

是不是感觉很蹊跷?

首先,在我的设备上,int是4字节,所以buff_2总共40字节,memset会对40个1字节赋值0X01,而不是对10个4字节赋值0X01。所以不要用memset对非字符型数组赋初值!

 

责任编辑:张燕妮 来源: CPP开发者
相关推荐

2020-11-08 14:38:35

JavaScript代码开发

2021-08-29 18:36:17

MySQL技术面试题

2009-07-23 15:07:32

2017-07-14 09:29:45

AndroidWebview

2011-04-26 09:22:05

SQLite

2019-10-28 14:07:29

研发管理技术

2021-04-04 22:31:26

白帽子厂商漏洞

2023-03-13 07:41:34

分页查询数据排序

2018-04-25 10:57:00

AIX报错vios

2021-05-27 09:27:35

开发技能缓存

2023-11-12 23:08:17

C++初始化

2024-03-13 08:52:43

C++初始化方式

2020-09-24 10:49:09

iOSiPadOSBug

2019-12-05 08:44:20

MybatisSQL场景

2024-03-18 08:14:07

SpringDAOAppConfig

2022-10-20 18:00:59

OCP模型参数

2021-12-26 14:32:11

缓存数据库数据

2017-09-07 15:23:21

神经网络数据网络

2011-06-09 14:13:06

C++JAVA缺省初始化

2010-02-01 14:21:24

C++初始化列表
点赞
收藏

51CTO技术栈公众号