概要:数组是由一组同类型的元素组成的集合,在内存上是一片连续的存储空间。C++提供了三种数组的表示方法:普通数组,模板类vector(C++98 新增的标准模板库STL提供该模板类)和模板类array(C++11新增)

下面分别讨论这三种类型的数组是如何使用的以及他们的区别:

一,这三种数组如何被定义?初始化?元素如何被访问?

(1)普通数组

普通数组定义和初始化:

typename vt[n_elem];      //数组vt长度n_elem必须是定常量或常量表达式

int a1[10]={1,3,4};  //定义由10个int型变量的数组a1,并用列表中数值依次对数组元素进行初始化(不足项默认为0)

int a1[]={1,3,4};     //定义由3个int型变量的数组a1,(这里定义数组时长度可以省略)

char a1[]="i i"       //定义由4个char型变量组成的数组a1(注意别忘了字符串中间的空格和字符串结尾省略的空字符,另外中文字符占2字节,英文、空格、结尾空字符都占一个字节)

普通数组元素的访问:

int a1[3]={1,3,4};

cout<<a1[2]<<*(a1+2)<<endl;    //可以通过数组名和元素下标来访问数组的元素;a1[2]相当于*(a1+2),数组名a1被解析为第一个元素的地址,这里即引用第一个元素往后移动两个元素位置的地址上数值。

int p1=a1;                                  //使用指针指向数组首地址后即可像数组名那样访问数组元素(而且是引用不是copy),

cout<<p1[2]<<endl;                  //p1[2]相当于a1[2],  即p1[2]---a1[2]---*(p1+2)---*(a1+2)

int p2=&a1[1];

cout<<p2[1]<<*(p2+1)<<*(a1+1+1)<<a1[2]<<end;           //这三者等

(2)模板类vector(动态数组)

模板类vectot的定义和初始化:

vector<typename>vt(n_elem);  //注意,vector对象vt的长度n_elem可以是常量也可以是变量;在运行阶段根据实际需要设置它的长度;

#include<vector>

...

using name space std;

//

vector<int> a2;     创建由0个int型变量组成的vector对象,内存为0;

a2.push_back(0)

a2.push_back(1)       //.push_back为vector模板类的一个方法,用于给数组扩容,即往数组尾部插入变量;注意,这里不能用a2[i]=数值;否则因vector数值越界而程序中断;

a2.push_back(2)     //vector对象的存储空间每次扩大时都会重新申请一片空间,然后将旧空间存储的值copy过来,最后将就空间释放;所以vector功能虽强,但代价是效率低。

//

vector<int>a2(10); //创建由10个int变量组成的vector对象;

a[0]=0;

...

a[9]=9;     //注意,C++98不支持用列表初始化vector对象,仅普通数组和array对象支持列表初始化;但在C++11新增了vector的列表初始化;

模板类vectot对象的元素访问:

同上面普通数组,可用vector对象名和元素下标访问a2[i],也可以用指向vector对象的指针访问 ;注意区别在于vector对象名不能被解析为第一个元素的地址。

int n;
    cin >>n;
    vector<int>a2(n);
    a2[2] = 2;
    int* p = &a2[0];
    cout << a2[2] << p[2] << *(p + 2);       //这三者等效

*遗留问题1:vector对象内存空间如何缩小?具体的原理是什么?

(3)模板类array

模板类array的定义和初始化

array<typename,n_elem>vt;      //同普通数组一样,创建array对象必须指定长度,n_elem须是常量或常量表达式。

#include<array>

...

using name space std;

array<int ,3>a3={1,2,3}   //定义由三个int型变量组成的array对象,并用列表里数值对array对象的元素进行初始化。

模板类array对象的元素访问:

对array对象的元素进行访问时,同普通数组和vector对象一样,都能通过对象名和元素下标进行访问,或者用指向对象的指针进行访问,

但同样,array对象名和vector对象名一样,不能像普通数组名称那样被解析为首元素的地址,即&a2[0]不等同于a2,&a3[0]不等同于a[3]

示例如下:

array<int, 3>a3 = { 1,2,3 };
    int* p = &a3[0];
    cout << a3[2] <<p[2]<<*(p+2) << endl;

二,三种数组的比较

1-就灵活性和功能上来说,模板类vecotor具有更高的灵活性,体现在其定义时不用指定具体的长度,而是可以在程序运行时根据需要确定其长度大小,另外,当vector对象的存储空间不够用时,会自动扩容,而无需手动分配内存。

2-就效率而言,由于vector对象每次扩容时都会重新申请一片更大的内存空间,然后将数据从原来的存储空间copy过来,再释放原来的存储空间;这样的过程将大大降低效率;而普通数组与array对象都是长度固定的,也使用栈(静态内存分配),而不是自由存储区,因此二者效率一样,都比vector高效。

3-安全性上:C++/C不会检查数组越界的情况,如a1[-2]=3,而array和vector提供了检查数组越界的方法.at(),使用at(i)访问元素时,会先判断小标i是否合法,从而提高了安全性。

4-方便性,vector和array对象可以进行赋值操作,而内置数组只能逐个元素copy,另外,vector和array有很多方便的api 如获取长度.size(),判断是都为空.empty(),而数组只能通过sizeof() / strlen()以及遍历计数来获取大小和是否为空。

5.vector和array提供了更好的遍历机制,即有正向迭代器和反向迭代器
   6.vector和array提供了两个容器对象的内容交换,即swap()的机制,而数组对于交换只能通过遍历的方式逐个交换元素
   7.array提供了初始化所有成员的方法fill()
   8.由于vector的动态内存变化的机制,在插入和删除时,需要考虑迭代的是否有效问题
   9.vector和array在声明变量后,在声明周期完成后,会自动地释放其所占用的内存。对于数组如果用new[] / malloc申请的空间,必须用对应的delete[]和free来释放内存

10.array对象和数组存储在相同的内存区域(栈)中,vector对象存储在自由存储区(堆)。

------------总结

通过以上比较,以后如需动态数组,使用vector,如需固定长度数组,选用array.

另外,学习栈和堆后回顾一下array和内置数组、vector的存储原理。

数组基础篇(对应C++ Primer plus 4.10)的更多相关文章

  1. 小猪猪C++笔记基础篇(四)数组、指针、vector、迭代器

    小猪猪C++笔记基础篇(四) 关键词:数组,Vector. 一.数组与指针 数组相信大家学过C语言或者其他的语言都不陌生,简单的就是同一个变量类型的一组数据.例如:int a[10],意思就是从a开始 ...

  2. 前端总结·基础篇·JS(二)数组深拷贝、去重以及字符串反序和数组(Array)

    目录 这是<前端总结·基础篇·JS>系列的第二篇,主要总结一下JS数组的使用.技巧以及常用方法. 一.数组使用 1.1 定义数组 1.2 使用数组 1.3 类型检测 二.常用技巧 2.1 ...

  3. Python学习笔记——基础篇【第五周】——算法(4*4的2维数组和冒泡排序)、时间复杂度

    目录 1.算法基础 2.冒泡排序 3.时间复杂度 (1)时间频度 (2)时间复杂度 4.指数时间 5.常数时间 6.对数时间 7.线性时间 1.算法基础  要求:生成一个4*4的2维数组并将其顺时针旋 ...

  4. 【Java 基础篇】【第二课】基本数组类型

    就像第一章所说一样,这次学习为了快,因此说明性的文字就不想写太多了,直接帖代码吧,代码当中尽量加一些注释: package a.b; public class test { static void B ...

  5. Java学习日记基础篇(七) —— 数组、排序

    数组 为什么要有数组? 案例:一个养鸡场有六只鸡,他们的体重分别为3kg,5kg,1kg,3.4kg,2kg,50kg.请问这六只鸡的总体重和平均体重是多少? public class test5 { ...

  6. iOS10 推送必看(基础篇)

    虽然这篇文章比较长,也不好理解,但是还是建议大家收藏,以后用到的时候,可以看看,有耐心的还是读一读. 这篇文章开始,我会跟大家好好讲讲,苹果新发布的iOS10的所有通知类. 一.创建本地通知事例详解: ...

  7. oracle(sql)基础篇系列(五)——PLSQL、游标、存储过程、触发器

      PL/SQL PL/SQL 简介 每一种数据库都有这样的一种语言,PL/SQL 是在Oracle里面的一种编程语言,在Oracle内部使用的编程语言.我们知道SQL语言是没有分支和循环的,而PL语 ...

  8. 一步步学习javascript基础篇(3):Object、Function等引用类型

    我们在<一步步学习javascript基础篇(1):基本概念>中简单的介绍了五种基本数据类型Undefined.Null.Boolean.Number和String.今天我们主要介绍下复杂 ...

  9. 《量化投资:以MATLAB为工具》连载(1)基础篇-N分钟学会MATLAB(上)

    http://blog.sina.com.cn/s/blog_4cf8aad30102uylf.html <量化投资:以MATLAB为工具>连载(1)基础篇-N分钟学会MATLAB(上) ...

随机推荐

  1. vite创建vue3项目 vueconfig配置及其备注

    import vue from '@vitejs/plugin-vue' const path = require('path') // vite.config.js # or vite.config ...

  2. XCTF练习题---MISC---hong

    XCTF练习题---MISC---hong flag:BCTF{cute&fat_cats_does_not_like_drinking} 解题步骤: 1.观察题目,下载附件 2.下载文件后发 ...

  3. 团队Beta1

    队名:观光队 链接 组长博客 作业博客 组员实践情况 王耀鑫 **过去两天完成了哪些任务 ** 文字/口头描述 任务分配 展示GitHub当日代码/文档签入记录 接下来的计划 完成短租车,页面美化 * ...

  4. 详解计算miou的代码以及混淆矩阵的意义

    详解计算miou的代码以及混淆矩阵的意义 miou的定义 ''' Mean Intersection over Union(MIoU,均交并比):为语义分割的标准度量.其计算两个集合的交集和并集之比. ...

  5. 老生常谈系列之Aop--Spring Aop源码解析(二)

    老生常谈系列之Aop--Spring Aop源码解析(二) 前言 上一篇文章老生常谈系列之Aop--Spring Aop源码解析(一)已经介绍完Spring Aop获取advice切面增强方法的逻辑, ...

  6. IIS方式部署项目发布上线

    VS2019如何把项目部署和发布 这里演示:通过IIS文件publish的方式部署到Windows本地服务器上 第一步(安装IIS) 1.在自己电脑上搜索Windows功能里的[启用或关闭Window ...

  7. height不确定时,如何使用动画效果展开高度

    要点: 当元素 height 不确定时,可以使用 max-height 设置动画效果 a[href="foldBox"] 用于打开 #foldBox(利用伪元素 :target) ...

  8. JS 加载

    DOM 加载完毕后执行,不需要等待image.js.css.iframe等加载 1.$(function() {}) 2.$(document).ready(function() {})  不要写成 ...

  9. .NET 中 GC 的模式与风格

    垃圾回收(GC)是托管语言必备的技术之一.GC 的性能是影响托管语言性能的关键.我们的 .NET 既能写桌面程序 (WINFROM , WPF) 又能写 web 程序 (ASP.NET CORE),甚 ...

  10. Docker容器的数据卷

    一.数据卷概念 1.数据卷是宿主机中的一个目录或文件 2.当容器目录和数据卷目录绑定后,对方的修改会立即同步 3.一个数据卷可以被多个容器同时挂载 4.一个容器也可以挂载多个数据卷 简单理解:有点类似 ...