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

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); 看起来很合理,但其实不行。事实上这对圆括号不是数组元素的构造参数, 可能是整个数组的,它有三个重载版本:
看起来像是常引用、右值引用、和默认版本。所以假如已经有一个相同大小的数组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的操作,失之毫厘谬以千里!

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

C/C++数组初始化的一些误区相关推荐

  1. C++: 数组初始化

    文章目录 栈 动态数组 赋值 memset fill 栈 数组是底层数据类型,存放在栈中,其内存的分配和释放完全由系统自动完成. 通过如下代码初始化一个全局变量数组,初始化的规则就是不足数组大小的按默 ...

  2. Java数组初始化的内存分配

    1.Java数组是静态的 Java是静态语言,所以Java的数组也是静态的,即:数组被初始化后,长度不可变 静态初始化:显式指定每个数组元素的初始值,系统决定数组长度 String[] books = ...

  3. 【C】数组数组初始化总结

    C数组初始化总结 发现一个新方法,可以分段初始化数组 eg:int arrayC[MAX_LEN] = {[1 - 5]=9, [6 - 9] = 8}; 代码如下 #include <stdi ...

  4. JAVA学习笔记--数组初始化

    JAVA中,数组只是相同类型的.用一个标识符名称封装到一起的一个对象序列或基本类型数据序列.数组通过方括号下标操作符[]来定义和使用,要定义一个数组只需在类型名后面加上一个方括号即可,如: int[] ...

  5. C语言中字符数组初始化的几种方法

    欢迎关注我的微信公众号:CurryCoder的程序人生 1.C语言中的字符数组初始化 在C语言中,字符串是当做字符数组来处理的:所以字符串有两种声明方式,一种是字符数组,一种是字符指针. 1.1 直接 ...

  6. 【C 语言】数组 ( 数组本质 | 数组长度定义 | 数组初始化 | 编译时初始化 | 显式初始化 - 重置内存 )

    文章目录 一.数组本质 二.数组长度定义 三.数组初始化 1.编译时初始化 2.显式初始化 ( 重置内存 ) 一.数组本质 数组本质 : 类型角度 : 从 数组元素 类型角度分析 , 数组是 相同类型 ...

  7. golang二维数组初始化

    golang二维数组初始化来看一下,有点特别 func main() {x := 2y := 4table := make([][]int, x)for i := range table {table ...

  8. 二维数组初始化的形式有?

    二维数组初始化的形式有? 数据类型 数组名[整常量表达式][ 整常量表达式]={ 初始化数据 }: 在{ }中给出各数组元素的初值,各初值之间用逗号分开.把{ }中的初值依次赋给各数组元素. 有如下几 ...

  9. c的关于数组初始化 和 memset用法

    今天为了彻底搞定一个关于c中数组初始化和声明不同情况下,比如只声明一个数组char str[20];那么这str里面是什么内容呢?我用vc6++,debug下看到都是-56饿asc码,后来请教了一个华 ...

最新文章

  1. python电脑配置要求cpu-python指定cpu使用率,与内存占用率
  2. zuul转发的一些常见异常
  3. apache camel_Apache Camel请向我解释这些端点选项的含义
  4. 4位院士的4个正确决定,成功扭转疫情!建议人人都该知道
  5. CSS中文档流之普通流,浮动及定位、浮动特性及清除浮动的方式、定位模式,子绝父相搭配定位方式、z-index层级
  6. lisp如何将度分秒转换为弧度_重磅干货!如何利用Stata进行空间冷热点分析 | 社论前沿...
  7. 最大流算法(Edmons-Karp + Dinic 比较) + Ford-Fulkson 简要证明
  8. loadRunner函数之lr_set_debug_message
  9. Apache Spark Meetup China 第1期 最全资料下载
  10. LabVIEW使用 NI Package Manager(NIPM)修复软件
  11. idea 配置SVN
  12. 视频分配器(视频放大分配器)
  13. python352的值为_Python3高级基础(2)
  14. 2020iOS开发工程师面试题汇总(内含面试技巧)-看完BATJ面试官对你竖起大拇指!
  15. 多模态预训练模型综述
  16. Java 常用工具类
  17. GBA程序开发入门1
  18. Nginx的启动安装和常用配置例子
  19. MySQL批量导入Excel、txt数据
  20. 03 - 程序设计框架:裸机编程中应用层、中间层、驱动层划分

热门文章

  1. java 增强for循环(foreach)
  2. 《Java程序设计》第十一周学习总结
  3. Beta 冲刺 (7/7)
  4. 24、嵌合体序列Chimeras
  5. 新安装Ubuntu加载时提示“为/检查磁盘时发生严重错误”的解决方法
  6. zoj 1010 (线段相交判断+多边形求面积)
  7. 《学习vi编辑器》的学习笔记1
  8. DateReader,DateAdapter,DateSet和SqlCommand的基本使用方法
  9. java多线程w3c_Java创建多线程的三种方式
  10. android使用webview上传文件,Android项目中如何在webview页面中上传文件