C++数组概述


基本概念

1. 数组是固定大小的一种复合类型

  • 因为数组是固定大小,所以在编译期间就决定了基大小
  • 数组的内存是连续(无论是一维数组还是多维数组)

2. 数组的特性

  • 数组之间不允许拷贝和赋值
  • 数组名是常指针

数组的操作

1. 数组的初始化

  • 数组定义时不初始化,则会被初始化为未初始化值
int nArr[4]; // 当数组为全局变量时,未初始化值默认为0;当数组为局部变量时,则其值在Debug下为0xccccccc,Release下为随机值
  • 大括号显式初始化
int nArr1[4] = {1, 2, 3, 4};
int nArr2[4] = {1, 2, 3}; // 第4值默认为0
int nArr3[] = {1, 2, 3, 4}; // 编译器在编译阶段推断数组维数为4
int nArr4[][4] = {1, 2, 3, 4, 5, 6, 7, 8}; // 数组最高维可以在编译阶段推导出为2
int nArr5[][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}}; // 数组最高维可以在编译阶段推导出为2
int nArr6[][4] = {{1}, {5}}; // 数组最高维可以在编译阶段推导出为2,剩下的默认为0
int nArr7[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}}; // 数组大小与赋值必须匹配
  • 字符数组
char szArr[] = "abcd"; // 编译器在编译阶段推断数组维数为5

2. 数组的大小

int nArr1[4] = {0};         // sizeof(nArr1)为16,因为nArr1是int[4]类型
int nArr2[3][4] = {0}; // sizeof(nArr2)为48,因为nArr2是int[3][4]类型

3. 数组与引用

int nArr6[][4] = {{1}, {2}, {3}}; // 数组最高维可以在编译阶段推导出为2,剩下的默认为0
int (&nArr7)[4] = nArr6[1]; // nArr7即是nArr6[2]的引用
int nArr8[4] = {0};
int (&nArr9)[4] = nArr8; // nArr9即是nArr8的引用

4. 数组与指针

	int nArr1[4] = {0};
int nArr2[3][4] = {0};
int *p1 = nArr1;
int *p2 = nArr2[1];
int *p3 = &nArr2[1][0]; // p2,p3是相等的
int (*p4)[4] = nArr2; // 此处的数组名nArr2退化为指针,p4是指针,指向int [4]类型数组首地址
int (*p5)[4] = &nArr2[0]; // p4,p5也是相等的
int *p6[4]; // p6是数组,存放4个int类型指针。sizeof(p6)=16
int* p7[4]; // 因为[]的优先级最高,所以p6,p7是相同的

5. 数组类型别名

typedef int intArray[4];
typedef int int2DArray[3][4];
intArray arr1 = {0};
int arr2[4] = {0};
// arr1,arr2是等价的
int2DArray arr3 = {0};
int arr4[3][4] = {0};
// arr3,arr4是等价的

6. 数组作为函数参数

-值与数组 因为数组不能拷贝,所以数组理论上不能作为值传递的形参。但事实上,我们有看到直接用数组作为参数值传递的,这明显违背数组拷贝的原理。如下段代码,其实是特殊情况,arr其实并不是数组类型,arr在作为形参时已经自动退化成指针了。

void Test(int arr[4])
{
*arr = 4;
int nSize = sizeof(arr); // 因为arr退化成指针,所以nSize=4
}
void Test1(int arr[])
{
int nSize = sizeof(arr); // 因为arr退化成指针,所以arr[]的维数写不写无影响
}
void Test2(int arr[][4])
{
int nSize = sizeof(arr); // 因为arr退化成指针,所以arr[]的维数写不写无影响,nSize=4
}
void Test3(int (*arr)[4])
{
int nSize = sizeof(arr); // Test3和Test4是等价的
}
  • 引用与数组

    数组类型的引用是合法的,引用类型的数组是非法的。
void Test(int (&arr)[4])
{
int nSize = sizeof(arr); // 因为arr是int [4]类型,所以nSize=20,此处维数不能省
}
void Test1(int &arr[4]) // Error,arrays of references are illegal
{
}
  • 指针与数组
void Test(int (*arr)[4])
{
int nSize = sizeof(arr); // arr是指针,指向int [4]首地址
}
void Test1(int* arr[4])
{
int nSize = sizeof(arr); // arr看起来是int* [4]类型,是数组,但是数组不能拷贝,所以退化成指针
}
void Test2(int* arr[])
{
int nSize = sizeof(arr); // arr[]退化成指针,Test2和Test1造价,nSize=4
}

7. 数组作为函数返回值

  • 返回值 因为返回值也会生成拷贝,所以与数组不能拷贝相违背,所以数组值不能作为函数返回。
  • 返回引用

    引用的数组是非法的,所以只能返回数组的引用
int (&Test)() [4]  // 返回的值优先引用,然后因为数组的引用,所以数组在引用后
{
int nArr[4] = {1, 2, 3, 4};
return nArr;
}
int (&nTemp)[4] = Test();
// 上面返回引用的方式难理解,我们可以换一种方式
typedef int intArray[4];
intArray& Test() // 利用typdef简单数组类型
{
int nArr[4] = {1, 2, 3, 4};
return nArr;
}
intArray& nTemp = Test();
// C++11引用了类型推导,可以用下面形式
int nArr[4] = {0, 1, 2, 3};
decltype(nArr)& Test23()
{
return nArr;
}
  • 返回指针

    因为数组不能拷贝,所以不能返回指针类型的数组(int* [4]),但可以返回指向数组的指针。
int nArr[3][4] = {{4}, {1, 5}, {2}};
int (*Test())[4]
{
int (*pArr)[4] = nArr;
return pArr;
}
int (*pArr)[4] = Test();
// 用typedef,C++11也可以用decltype(代码略)
typedef int intArray[4];
int nArr[3][4] = {{4}, {1, 5}, {2}};
intArray* Test()
{
int (*pArr)[4] = nArr;
return pArr;
}
intArray* pArr = Test();

8. 数组与vector

  • 异同
  1. 相同点,数组与vector的内存都是连续的。
  2. 不同点,数组是固定大小,而vector是动态大小。
  • 相互转化

    数组可以看作是特殊的vector,所以一些适用于vector的算法,如sort,unique都是可以用于数组的。
int nArr[5] = {4, 3, 2, 1, 5};
sort(nArr, nArr+_countfof(nArr));
vector<int> vInt(nArr, nArr+_countfof(nArr));
// 因为vector内存是连续的,所以可以直接拷贝内存。
memcpy(nArr, &vInt[0], vInt.size()*sizeof(int));

C++数组概述的更多相关文章

  1. 054 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 01 数组概述

    054 01 Android 零基础入门 01 Java基础语法 06 Java一维数组 01 数组概述 本文知识点:数组概述 为什么要学习数组? 实际问题: 比如我们要对学生的成绩进行排序,一个班级 ...

  2. 【搬砖】安卓入门(4)- Java开发编程基础--数组

    05.01_Java语言基础(数组概述和定义格式说明)(了解) A:为什么要有数组(容器) 为了存储同种数据类型的多个值 B:数组概念 数组是存储同一种数据类型多个元素的集合.也可以看成是一个容器. ...

  3. C#数组

    数组是一种数据结构,它包含若干相同类型的变量.数组是使用类型声明的: type[] arrayName; 下面的示例创建一维.多维和交错数组: class TestArraysClass { stat ...

  4. C#数组全解

    数组概述 C# 数组从零开始建立索引,即数组索引从零开始.C# 中数组的工作方式与在大多数其他流行语言中的工作方式类似.但还有一些差异应引起注意. 声明数组时,方括号 ([]) 必须跟在类型后面,而不 ...

  5. java之数组

    数组概述: 1.数组可以看成是多个相同数据类型数据的组合,对这些数据的统一管理. 2.数组变量属引用类型,数组也可以看成是对象,数组中的每个元素相当于该对象的成员变量. 3.数组中的元素可以是任何类型 ...

  6. java总结第二次//数组及面向对象

    三.java数组 主要内容:数组概述.一维数组声明.数组元素的引用.数组元素的默认初始化.创建数组.数组初始化.多维数组.多维数组初始化.数组排序 1.数组概述 数组是多个相同类型数据的组合,实现对这 ...

  7. java面向对象编程——第六章 数组

    1.数组概述 数组是存储在一个连续的内存块中的元素集合.数组中的每个元素必须是相同的数据类型,并且通过索引进行区分.数组中的第一个元素的索引为0. 在java中,创建数组有两个步骤: 声明一个对数组的 ...

  8. c#字符串及数组操作

    字符串操作(取当前时间)string time=convert.tostring(DateTime.Today).split( new char []{' '});    textbox1.text= ...

  9. 细说php(六) 数组

    一.数组概述 1.1 数组是复合类型 1.2 数组中能够存储随意长度的数据, 也能够存储随意类型的数据 二.数组的类型 2.1 索引数组: 下标是顺序整数作为索引 <?php $user[0] ...

随机推荐

  1. Web 版 powerdesigner (Canvas) 技术分享

    演示地址:http://www.netuml.com:8088  <canvas></canvas>是HTML5出现的新标签,像所有的dom对象一样它有自己本身的属性.方法和事 ...

  2. c# 内存的具体表现- 通用类型系统 深拷贝 浅拷贝 函数传参

    c# 通用类型系统 及变量在 深拷贝 浅拷贝 函数传参 中的深层次的表现 在编程中遇到了一些想不到的异常,跟踪发现,自己对于c#变量在内存上的表现理解有偏差,系统的学习并通过代码实验梳理了各种情况下, ...

  3. WPF学习随笔

    内容控件 Padding内边距,Margin外边距 1.ScrollViewer滚动条控件 <ScrollViewer VerticalScrollBarVisibility="Vis ...

  4. Django项目部署到Apache服务器

    本文讲述的是在阿里云服务器(ECS)上部署Django项目于Apache,服务器操作系统为ubuntu,公网Ip地址为123.56.30.151. 将Django部署到Apache服务器的原因 Dja ...

  5. React入门---开始前的准备(下)-3

    React开始前的准备(下): ·配置webpack热加载(热加载就是修改js文件,点击保存之后,浏览器会自动刷新,提高开发效率) 1. 全局安装: npm install webpack -g np ...

  6. Windows下快速安装Xgboost(无需Git或者VS)

    xgboost的全称是eXtreme Gradient Boosting,现在已经风靡Kaggle.天池.DataCastle.Kesci等国内外数据竞赛平台,是比赛夺冠的必备大杀器!如果把数据竞赛比 ...

  7. Enum in Java

    1. Enum Class public enum ContainerPropertyConstants { RETAILER("retailer"), LINED("i ...

  8. 开涛spring3(7.3) - 对JDBC的支持 之 7.3 关系数据库操作对象化

    7.3.1  概述 所谓关系数据库对象化其实就是用面向对象方式表示关系数据库操作,从而可以复用. Spring JDBC框架将数据库操作封装为一个RdbmsOperation,该对象是线程安全的.可复 ...

  9. click和blur事件冲突解决方案

    场景:例如做一个模仿百度搜索的搜索框,输入文字下面会有匹配项,当点击下拉项中的值时,就将值添加到搜索框中同时隐藏下拉框,点击其他地方就直接隐藏下拉框,这时所需要的事件分别为 下拉框事件onclick, ...

  10. 刨根究底字符编码之八——Unicode编码方案概述

    Unicode编码方案概述   1. 前面讲过,随着计算机发展到世界各地,于是各个国家和地区各自为政,搞出了很多既兼容ASCII但又互相不兼容的各种编码方案.这样一来同一个二进制编码就有可能被解释成不 ...