关于C++数组初始化的一些坑之原理剖析

关于C++数组初始化的一些坑之原理剖析

前情提要

在开始之前先介绍几种数组初始化的语法:

将数组初始化为0,有以下几种常用方案
1. int arr[10]{0};
2. int* arr = new int[10]{0};//分配到堆内存
3. int arr[10] = {0};//或者 int arr[10];//默认初始化为0
4. vector<int> vec(10,0);//或者vector<int> vec(10);//默认也是初始化为0

值得注意的是,C++11之后才支持1和2两种初始化语法。

正文

我们先看一行代码:

int arr[10] = {-1}; 

请问如果遍历该数组,得到的结果会是什么呢?

答案是:-1 0 0 0 0 0 0 0 0 0

如果你的答案是正确的,而且你明白是怎么一回事就不需要往下看了。

这是我在刷 PAT 1039 到底买不买 这道题时遇到的问题,花了N多天的时间思考、查资料,终于弄清楚原理了,在这里跟各位道友分享一下。

一开始,我也天真地以为数组元素是10个-1,直到PAT报错……

其实,全部初始化为0是完全没问题的,问题就出在想把数组全部初始化成一个非0的数,即非默认值,是行不通的。这倒不是因为编译器对初始化为0给了个特例,而是因为一条基本语法规则:
数组初始化列表中的元素个数小于指定的数组长度时,不足的元素补以默认值。
而对于基本类型int来说,默认值就是0。

再看一下非基本类型的数组:

string a[5] = { "foo" };

有了上面的规则,就很容易知道其实相当于:

string a[5] = { "foo", "", "", "", "" };

也就是说,后面4个元素调用了string的默认构造函数进行的初始化,而第一个则调用的string::string(const char)进行的初始化

memset的误区

如果想在数组创建结束后再对其进行初始化,可以使用C函数memset(),但是memset的使用有个大问题,就是它只对char类型的数组管用:

char a[10];
memset(a, 1, 10); // 将每个元素设置为1

如果将上面的a数组换成int或其他类型的,就会出现问题,因为memset的内部实现是以字节为单位进行赋值的,int 类型大于一个字节(假设是4个),数组内存连续,如果有下面代码:

int a[10];
memset(a, 1, sizeof(a));

将只会对前sizeof(a)即40个字节进行赋值1的操作,即给“前10个int”进行了赋值0x01010101的操作,所以,如果实在想再初始化,只能循环赋值。

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值