C/C++数组初始化的一些误区

C/C++数组初始化的一些误区以前我这样初始化一个数组,并自我感觉良好:inta[5]={0};//全部初始化为0这种简单的写法让我非常爽,于是我又想把数组全部初始化为1:inta[5]={1};//我想全部初始化为1直到十分钟前,我都以为这句代码确实能够将5个元素全部初始化为1,但事实跟我想的完全不同!(基础的东西革命的本钱,疏漏不得啊)全部初始化为0的那行代码确实是没问题的,可以

大家好,又见面了,我是你们的朋友全栈君。

以前我这样初始化一个数组,并自我感觉良好:

int a[5] = { 0 };    // 全部初始化为0

这种简单的写法让我非常爽,于是我又想把数组全部初始化为1:

int a[5] = { 1 };    // 我想全部初始化为1

直到十分钟前,我都以为这句代码确实能够将5个元素全部初始化为1,但事实跟我想的完全不同!(基础的东西革命的本钱,疏漏不得啊)

全部初始化为0的那行代码确实是没问题的,可以正常工作。问题就出在想把数组全部初始化成一个非0的数,即非默认值,是行不通的(查看内存发现,只有数组的第一个元素被初始化为1,其他全为0)。这倒不是因为编译器对初始化为0给了个后门,而是因为一条基本语法规则:

数组初始化列表中的元素个数小于指定的数组长度时,不足的元素补以默认值。

对于基本类型int来说,当然就是补int()即0了。再看一下非基本类型的数组:

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

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

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

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

还有一个区别:

int a[5];
string a[5];

如果不明确指出初始化列表,那么基本类型是不会被初始化的(除全局变量和静态变量外),所有的内存都是“脏的”;而类类型则会为每个元素调用默认构造函数进行初始化。

注意,在C++11中中间的赋值号可以省略,即 int a[5]{1}; 并且,如果初始化列表为空,如 int a[5]{},那将初始化所有元素为默认值,即与 int a[5]{0}; 等价


动态数组的初始化

说完了栈中的数组的初始化,我发现new一个数组和其又有一些不同:

int* a = new int[5];
string* a = new string[5];
int* a = new int[5] { 0 };
string* a = new string[5] { "foo" };

上面几行代码遵循栈中数组的初始化规则,除此之外这里还有一个新语法:

int* a = new int[5]();

注意后面的一对圆括号,它的意思是使用默认值初始化整个数组,所以对于类类型来说,new string[5] 与 new string[5]()是等价的,都会调用默认构造函数进行初始化;但是对于基本类型就不同了,new int[5]根本不会初始化,而new int[5]() 则会使用int()的值即0进行初始化。

看到这对圆括号,我想它该不会是元素的构造函数的参数列表吧,那么我可能会想将数组全部初始化为1:new int[5](1); 看起来很合理,但其实不行。事实上这对圆括号不是数组元素的构造参数,
可能是整个数组的,它有三个重载版本:

C/C++数组初始化的一些误区
C/C++数组初始化的一些误区
C/C++数组初始化的一些误区


看起来像是常引用、右值引用、和默认版本。所以假如已经有一个相同大小的数组b,试着用b来初始化a:

int* a = new int[5](b);

结果编译出错,提示error C3074: an array cannot be initialized with a parenthesized initializer,看来这个括号的作用和我想的不一样,其实也应该看出来的,要是是用另一个数组初始化的话那么参数应该是const int (&)[5] 而不是 const int [5] &,而且后者好像是一个错误的类型。这个问题暂时无解。

错过了初始化时机(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的操作,即给“前5个int”进行了赋值0x01010101的操作,失之毫厘谬以千里!

如果实在想再初始化,那么老老实实循环赋值吧。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/161046.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • WinSCP连接linux系统root登录时拒绝访问解决办法

    WinSCP连接linux系统root登录时拒绝访问解决办法1.编辑/etc/ssh/sshd_config文件:sudovi/etc/ssh/sshd_config将PermitRootLogin的值改成yes将PermitEmptyPassword的值改成no保存退出2.重启ssh:sudoservicesshrestart3.即可在WinSCP用root用户登陆转自https://blog.c…

    2025年12月13日
    4
  • ArcGIS server 10.2安装教程详细版

    ArcGIS server 10.2安装教程详细版详细讲述arcgisserver10.2的安装教程。默认已经安装arcgisDesktop10.2。提供一个arcgisserver下载地址:链接:https://pan.baidu.com/s/1iXol6v3RiqjU2MLvbnwNFA提取码:7fzf(失效了请和我说)一、所需文件1.ArcgisServer10.2安装文件。2.ArcgisSer…

    2022年5月25日
    75
  • sql 聚合语句,count的用法「建议收藏」

    sql 聚合语句,count的用法「建议收藏」如要获取result='1'的数量COUNT(CASEWHENresult='1'THENresultEND)SELECT*FROM(

    2022年7月2日
    31
  • java静态代理实现_静态注册和动态注册的优缺点

    java静态代理实现_静态注册和动态注册的优缺点思考:以常见的增删改查为例,在执行增删改的时候我们需要开启事务,执行完成后需要提交事务假如说你Service里有100个增删改的方法,那这100个方法里除了你自己真正需要处理的业务逻辑外,每个方法都还需要去关注开启事务,提交事务这些动作。那有没有稍微好点的办法解决呢?于是就出现了代理模式的概念,那什么是代理模式呢?1、什么是代理模式简单来说:代理就是对目标方法进行增强。什么意思呢?…

    2022年10月17日
    1
  • 计算机网络技术现代安防是啥意思,现代化校园视频安防监控系统 具有哪些特点呢…

    计算机网络技术现代安防是啥意思,现代化校园视频安防监控系统 具有哪些特点呢…原标题:现代化校园视频安防监控系统具有哪些特点呢校园视频安防监控系统主要是利用监控设备对学校场所进行全方位、全高清视频立体化管理和监控,从而维护校园秩序和安全,同时能为同学们的生活和学习营造更好的安全环境。那么现代化校园视频安防监控系统具有哪些特点呢?今天就和小编一起来学习了解下吧。1、可靠性与安全性校园视频安防监控系统的设计应具有较高的可靠性,在校园视频安防监控系统故障或事故造成中断后,能确…

    2022年6月28日
    27
  • MySQL配置文件配置

    MySQL配置文件配置MySQL配置文件

    2022年5月5日
    45

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号