专栏首页编程学习基地C++初始化的坑你也遇到过吗?

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

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

陷阱1:默认初始化的坑

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

int a;
void func()
{
    int b;
    static int c;
    cout<<"a: "<<a<<", b :"<<b<<", c :"<<c<<endl;
}
int main()
{
    cout<<"main a: "<<a<<endl;
    func();
    return 0;
}

打印结果是:

main a: 0
a: 0, b :32694, c :0

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

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

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

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

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

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

陷阱2:数组初始化的坑

int buff[10] = {0};
for(int i = 0;i<10;i++)
{
    cout<<buff[i]<<endl;
}

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

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

int buff_2[10] = {1};
for(int i = 0;i<10;i++)
{
    cout<<buff_2[i]<<",";
}

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

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

陷阱3:memset的坑

char buff[10];
memset(buff,0,sizeof(buff));
for(int i = 0;i<10;i++)
{
    printf("%d ",buff[i]);
}

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

int buff_2[10];
memset(buff_2,1,sizeof(buff_2));  
for(int i = 0;i<10;i++)
{
    printf("%d ",buff_2[i]);
}

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

16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009

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

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

改为:

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

得到的结果是:

0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101

是不是感觉很蹊跷?

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

关于C++初始化的坑,你遇到过哪些?欢迎在评论中和我探讨。觉得文章不错,请点赞和在看支持我继续分享好文。谢谢!

End

本文分享自微信公众号 - 编程学习基地(LearnBase)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2021-01-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java程序员求职热点问题总结(持续更新)

    废话!硕士都满地跑了,本科生更要努力提高自己技术实力才能进好公司!优秀的人一直很优秀,自己欠的也都是要还的!谁再说读书无用论,建议先转行收租。

    JavaEdge
  • 看到SpringBoot神一样集成Druid,我吐了!

    都说尽量不要在外包团队待太久,事实会告诉你一点都不假。最近接手外包团队的项目,发现很多问题。最令人难以接受的便是在SpringBoot集成Druid数据库连接池...

    程序新视界
  • 那些年在win下填过的Django坑

    專 欄 ❈ JacobYRJ,Python中文社区专栏作者 Python语言爱好者,目前在做Django项目。 Github博客:https://JacobY...

    Python中文社区
  • 3D 小游戏《飞跃地平线 Plus》开发分享

    近日,ID“woskymi”的开发者在 Cocos 社区分享了他采用 Cocos Creator 2.1.2 制作的 3D 小游戏《飞跃地平线 Plus》引发论...

    张晓衡
  • 【趣学程序】java基础知识(一)

    可以简单的理解为Java程序为了加强阅读行自定义的名称,如类名、方法名、变量名。仅仅是个名字而已。对于这样一个名字不像我们人类一样可以随意起名,程序有一定的命名...

    趣学程序-shaofeer
  • 【C/C++教程】关于C/C++那些坑爹的破事儿,你被坑了吗?

    那么,今天,就带大家看看C/C++里面究竟有多少不为人知的秘(keng)密(die)吧。可以测试一下,不看答案,自己能get到多少。

    短短的路走走停停
  • 人工智能时代最合适的语言,Python终于玩大了!

    自2017年国务院印发《新一代人工智能发展规划》,明确指出在中小学阶段设置人工智能相关课程后,Python一路逆袭, 作为人工智能时代最合适的语言,Python...

    一墨编程学习
  • 现有项目集成flutter排坑指南

    1、如果选择,stable,我们遇到的情况是,IOS上接入之后是跑不了的。切到master上就OK了。

    brzhang
  • 腾讯PM职场实录:工作13年后明白的5个道理,每一条都让你想哭

    腾讯大讲堂

扫码关注云+社区

领取腾讯云代金券