网站首页 > 基础教程 正文
谈及 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/C++编程知识的话!那么你很幸运~“点击下方链接”加入C/C++企鹅圈,这里还有一些你可能不知道的趣事分享哟。
猜你喜欢
- 2024-10-10 C++系列1-1:初探C++ c=2μf
- 2024-10-10 浅谈C++11(第9篇 可变参数模板) c++可变参数模板类
- 2024-10-10 数组的初始化方式有哪几种? 数组的初始化是什么意思
- 2024-10-10 c++对于内建类型的默认初始化 创建内部类的对象
- 2024-10-10 C++类构造函数,如何初始化对象?linux C++第27讲
- 2024-10-10 【C++编程语言】之 类和对象——对象的初始和消除
- 2024-10-10 C++基础语法梳理:引用、封装、继承和多态
- 2024-10-10 C++核心准则?:按照成员声明的顺序定义和初始化成员变量
- 2024-10-10 C++核心准则C.47:按照成员变量声明的次序定义和初始化数据成员
- 2024-10-10 C/C++语言编程系列002——不同情况下数组的初始化方法
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)