与vector的异同

  • 相同:都是存放类型相同对象的容器
  • 不同:数组的大小确定不变,不能随意向数组中增加元素

1、定义和初始化内置数组

  数组中元素的个数也属于数组类型的一部分,编译的时候维度应该是已知的,也就是说,维度必须是一个常量表达式。

  默认情况下,数组的元素被默认初始化。

NOTE:

  • 定义数组的时候必须制定数组类型,不允许用auto
  • 数组元素应为对象,不能是引用

显式初始化数组元素

  可以对数组元素进行列表初始化,此时允许忽略数组的维度。当指定了维度,则维度应比列表初始值的数量多,当维度比初始化列表的数量大时,多的部分默认初始化。

字符数组的特殊性

  字符数组允许用字符串字面值来进行初始化,但数组的维度必须比字符串字面值大1,用来盛放添加的空字符'/0';

  1. char a[]="hi";
  2. char a1[]="hi"; //错误,最后的空字符'/0'没地方放

不允许拷贝和赋值

  不能将数组的内容拷贝给其他数组作为初始值,也不能用数组为其他数组赋值

  1. int a[]={,,};
  2. int b[]=a; //不允许使用一个数组初始化另一个数组
  3. int b=a; //不允许把数组直接赋值给另一数组

理解复杂的数组声明

  数组本身也是对象,因此可以定义指向数组的指针和引用。

  1. int *ptrs[10]; //含有10个整型指针的数组
  2. int &refs[10]=a; //错误,不存在引用的数组,数组的元素必须是对象
  3. int (*Parray)[10]=&arr; //Parray指向一个含有10个整数的数组
  4. int (&arrRef)[10]=arr; //arrRef引用一个含有10个整数的数组

2、访问数组元素

  可以使用范围for语句或下标来访问数组元素

  在使用下标的时候,通常将其定义为size_t类型。size_t类型是一种机器相关的无符号类型,它被设计得足够大以便能表示内存中任意对象的大小。在cstddef头文件中定义了size_t类型。

  遍历数组所有元素,最好的方法是范围for语句。

检查下标的值

3、指针和数组

  在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针。

  对数组的元素使用取地址符就能得到指向该元素的指针。

指针也是迭代器

  指向数组元素的指针可以执行迭代器一样的操作。

  1. int a[] = { };
  2. int n = ;
  3. for (auto &i : a)
  4. {
  5. i = n;
  6. n++;
  7. }
  8. int *p1 = a; //相当于迭代器的begin
  9. int *p2 = &a[10]; //相当于迭代器的end
  10. for (int *p3 = p1; p3 != p2; p3++)
  11. {
  12. cout << *p3 << endl;
  13. }

标准库函数begin和end

  上述使用a[10]的地址来表示尾后指针很容易出错,因此标准库定义了数组用的begin和end函数来得到数组的首指针和尾后指针,其在iterator头文件中。

  1. int a[] = { };
  2. int n = ;
  3. for (auto &i : a)
  4. {
  5. i = n;
  6. n++;
  7. }
  8. /*int *p1 = a;
  9. int *p2 = &a[10];*/
  10. int *p1 = begin(a);
  11. int *p2 = end(a);
  12. for (int *p3 = p1; p3 != p2; p3++)
  13. {
  14. cout << *p3 << endl;
  15. }

二者同样的效果。

指针运算

  给指针加上一个整数,得到的新指针仍需指向同一数组的其他元素,或者指向同一数组的尾元素的下一位置。

解引用和指针运算的交互

  指针加上一个整数得到的结果仍是一个指针,因此可以解引用该指针。

下标和指针

  对数组执行下标运算其实是对指向数组元素的指针执行下标运算。

  1. int i=a[];
  2. //上面的下标引用其实是下面的过程
  3. int *p=a;
  4. i=*(p+);

  虽然标准库类型vector和string也能执行下标运算,但是数组与它们相比还是有所不同。标准库类型限定使用的下标必须是无符号类型,而内置的下标运算无此要求。

  1. int *p=&a[];
  2. int j=p[]; //实际是a[3]
  3. int k=p[-]; //实际上是a[0]

与旧代码的接口

混用string对象和C风格字符串

  C风格字符串:以空字符结尾的字符数组。

  string提供一个名为c_str()的成员函数来将string转换为C风格字符串,返回的是const char*类型。

使用数组初始化vector对象

   指明要拷贝区域的首元素地址和尾后地址即可。

  1. int a[]={,,,,,};
  2. vector<int> v(begin(a),end(a));

NOTE:不能用vector初始化数组。

  • 尽量不使用数组和指针,而使用vector和迭代器
  • 尽量不使用C风格字符串,而使用string

多维数组

  C++语言中没有多维数组,通常所说的多维数组其实是数组的数组。

  1. int a[][];  //大小为3的数组,每个元素是含有4个整数的数组
  2.  
  3. int b[][][];

多维数组的初始化

  使用花括号括起来的一组值初始化多维数组,和普通数组初始化一样,只是数组的元素也是数组而已。

  1. int a[][]={
  2. {,,,},
  3. {,,,},
  4. {,,,}};
  5.  
  6. int a[][]={,,,,,,,,,,,,}; //和上面的效果一样
  7.  
  8. int a[][]={{},{},{}}; //其余的默认初始化

多维数组的下标引用

  表达式含有的下标运算符数量和数组的维度一样多,该表达式的结果将是给定类型的元素;当比数组的 维度数量小时,表示的是内层数组。

使用范围for语句处理多维数组

  1. size_t cnt=;
  2. for(auto &row:a)
  3. for(auto &col:row)
  4. col=cnt;
  5. cnt++;
  6. }

NOTE:

  使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应用是引用类型。为了防止编译器将auto控制变量转换成数组首元素的指针。

指针和多维数组

  当程序使用多维数组的名字时,也会自动将其转换成指向数组首元素的指针。

  也可以通过使用auto或decltype来遍历多维数组

  1. int a[][] = {};
  2. int cnt = ;
  3. for (auto p = a; p != a + ; p++)
  4. {
  5. for (auto q = *p; q != *p + ; q++)
  6. {
  7. *q = cnt;
  8. cnt++;
  9. }
  10. }
  11. for (auto p = a; p != a + ; p++)
  12. {
  13. for (auto q = *p; q != *p + ; q++)
  14. {
  15. cout << *q << " | ";
  16. }
  17. cout << endl;
  18. }

也可以使用begin和end来简化

  1. int a[][] = {};
  2. int cnt = ;
  3. for (auto p = begin(a); p != end(a); p++)
  4. {
  5. for (auto q = begin(*p); q != end(*p); q++)
  6. {
  7. *q = cnt;
  8. cnt++;
  9. }
  10. }
  11. for (auto p = begin(a); p != end(a); p++)
  12. {
  13. for (auto q = begin(*p); q != end(*p); q++)
  14. {
  15. cout << *q << " | ";
  16. }
  17. cout << endl;
  18. }

类型别名简化多维数组的指针

  1. using int_array=int[];
  2. int a[][] = {};
  3. int cnt = ;
  4.  
  5. for (auto p = begin(a); p != end(a); p++)
  6. {
  7. for (auto q = begin(*p); q != end(*p); q++)
  8. {
  9. *q = cnt;
  10. cnt++;
  11. }
  12. }
  13. for (int_array *p = a; p != a + ; p++)
  14. {
  15. for (int *q = *p; q != *p + ; ++q)
  16. {
  17. cout << *q << " | ";
  18. }
  19. cout << endl;
  20. }

C++系统学习之四:数组的更多相关文章

  1. 【mongodb系统学习之四】查看mongodb进程

    四.查看mongodb进程(可以配合启动和关闭使用): 1).方法一:直接查看mongodb进程是否已经存在(用上面的方式启动后,需要另开一个窗口操作):ps –ef|grep mongodb, 如图 ...

  2. 系统学习 Java IO (七)----字节数组流 ByteArrayInputStream/ByteArrayOutputStream

    目录:系统学习 Java IO---- 目录,概览 ByteArrayInputStream 如果数据存储在数组中,ByteArrayInputStream 可以很方便读取,它可以返回 InputSt ...

  3. Linux系统学习笔记:文件I/O

    Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...

  4. Hibernate的系统 学习

    Hibernate的系统 学习 一.Hibernate的介绍 1.什么是Hibernate? 首先,hibernate是数据持久层的一个轻量级框架.数据持久层的框架有很多比如:iBATIS,myBat ...

  5. 系统学习NIO

    概述 适用于有一定编程基础的朋友,想系统学习NIO这块知识的朋友.知识点大体分3块:1:>概念了解(各类IO) 2>NIO的核心(缓存区,通道等) 3>网络IO 详细 代码下载:ht ...

  6. 系统学习 Java IO (十六)----这么多类,应该用哪个?

    目录:系统学习 Java IO---- 目录,概览 Java IO目的和功能 Java IO 包含 InputStream,OutputStream,Reader 和 Writer 类的许多子类. 原 ...

  7. 系统学习 Java IO (十四)----字符读写缓存和回退 BufferedReader/BufferedWriter & PushbackReader

    目录:系统学习 Java IO---- 目录,概览 BufferedReader BufferedReader 类构造器接收一个 Reader 对象,为 Reader 实例提供缓冲. 缓冲可以加快 I ...

  8. 系统学习 Java IO (十三)----字符读写 Reader/Writer 及其常用子类

    目录:系统学习 Java IO---- 目录,概览 Reader Reader 类是 Java IO API 中所有 Reader 子类的基类. Reader 类似于 InputStream ,除了它 ...

  9. 系统学习 Java IO (十)----回退流 PushbackInputStream

    目录:系统学习 Java IO---- 目录,概览 PushbackInputStream 旨在从 InputStream 解析数据时使用. 有时您需要先读取几个字节以查看将要发生的事情,然后才能确定 ...

随机推荐

  1. [Xcode 实际操作]八、网络与多线程-(10)使用异步Get方式查询GitHub数据

    目录:[Swift]Xcode实际操作 本文将演示如何通过Get请求方式,异步获取GitHub资源的详细信息. 异步请求与同步请求相比,不会阻塞程序的主线程,而会建立一个新的线程. 在项目导航区,打开 ...

  2. js 判断当前操作系统 ios, android, 电脑端

    一 .   js判断移动端的操作系统(ios或Android) $(function () { var u = navigator.userAgent; var isAndroid = u.index ...

  3. JMeter BeanShell示例

    翻译:https://blog.trigent.com/jmeter-blog-series-jmeter-beanshell-example 在这个例子中,我们将演示在Apache JMeter中使 ...

  4. POJ-1020-Anniversary Cake

    链接:https://vjudge.net/problem/POJ-1020 题意: 给一个宽为s的正方形,再给n个变长为an的小正方形, 判断是否能将这n个小正方形完全填充到这个大正方形里面. 思路 ...

  5. Mass Change Queries Codeforces - 911G

    https://codeforces.com/contest/911/problem/G 没想到线段树合并还能这么搞.. 对每个权值建一个线段树(动态开点),如果权值为k的线段树上第i位为1,那么表示 ...

  6. CentOS 部署RabbitMQ集群

    1. 准备两台CentOS,信息如下: node1:10.0.0.123 node2:10.0.0.124 修改hostname请参照: $ hostname # 查看当前的hostname $ ho ...

  7. 103 Binary Tree Zigzag Level Order Traversal 二叉树的锯齿形层次遍历

    给定一个二叉树,返回其节点值的锯齿形层次遍历.(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行).例如:给定二叉树 [3,9,20,null,null,15,7],    3   ...

  8. js获取窗口参数

    window.onscroll=function getScrollTop(){ console.log(scrollTop) if(document.documentElement&& ...

  9. Linux sftp用法

    sftp用法 1. 用sftp如何登录服务器 sftp 是一个交互式文件传输程式.它类似于 ftp, 但它进行加密传输,比FTP有更高的安全性.下边就简单介绍一下如何远程连接主机,进行文件的上传和下载 ...

  10. Spring MVC 入门实例报错404的解决方案

    若启动服务器控制台报错,并且是未找到xml配置文件,初始化DispatchServlet失败,或者控制台未报错404,那么: 1.URL的排查: 格式-----------协议名://地址:端口号/上 ...