数组

来源:互联网 发布:阿里云短信授权书 编辑:程序博客网 时间:2024/05/22 01:40

 数组是存放类型相同的对象的容器,这些对象本身没有名字,需要通过其所在位置访问。数组的大小确定不变,不能随意向数组中增加元素

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

 数组声明形如a[d],其中a是数组的名字,d是数组的维度。数组中元素的个数也属于数组类型的一部分,编译的时候维度应该是已知的,也就是说,维度必须是一个常量表达式。
 定义数组的时候必须指定数组的类型,不允许用auto关键字由初始值的列表推断类型。数组的元素应为对象,因此不存在引用的数组。

显示初始化数组元素

const unsigned sz = 3;int a1[sz] = {0,1,2};//允许忽略数组的维度,如果声明时没有指明维度,编译器会根据初始值的数量计算并推测出来。如果声明时指明了维度,那么初始值的总数量不应该超出指定的大小。int a2[] = {0,1,2};  //如果维度比提供的初始值数量大,则用提供的初始值初始化靠前的元素,剩下的元素被初始化成默认值int a3[5] = {0,1,2};  //等价于a3[5]={0,1,2,0,0};

字符数组的特殊性

//字符数组有一种额外的初始化方式,即用字符串字面值对数组初始化,当使用这种初始化方式时,一定要注意字符串字面值的结尾处还有一个空字符,这个空字符也会像其他字符一样被拷贝到字符数组中去:char a1[]={'C','+','+'};  //正确 ,列表初始化,维度为3char a2[]="C++";  //正确,自动添加表示字符串结束的空字符,维度为4char a3[3]="C++";  //错误,没有空间可存放空字符

不允许拷贝和赋值

不能讲数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值int a= {1,2,3};int a1[]=a;  //错误,不能用一个数组初始化另一个数组int a2[];a2=a;  //错误,不能用一个数组给另外一个数组赋值

理解复杂的数组声明

int *ptrs[10];  //ptrs是含有10个整数指针的数组int &refs[10];  //错误:不存在引用的数组,因为数组元素为对象int (*Parray)[10] = &arr;//Parray指向一个含有10个整数的数组int (&arrRef)[10] = arr;//arrRef引用一个含有10个整数的数组//array是数组的引用,该数组含有10个指针int * (&array)[10] = ptrs;

访问数组元素

 使用数组下标访问,访问时通常将其定义为size_t类型。数组的下标应在合理范围内,下标应大于等于0而且小于数组的大小。

2.指针和数组

 在C++语言中,指针和数组有非常紧密的联系,使用数组的时候编译器一般会把它转换成指针。
 通常情况下,使用取地址符来获取某个对象的指针,取地址符可以用于任何对象。数组的元素也是对象,对数组使用下标运算符得到该数组指定位置的元素。

string nums[]={"one","two","three"}; string *p=&nums[1];

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

string *p2=nums;  //等价于p2=&nums[0];//在大多数表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针

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

constexpr size_t sz = 5 ;int arr[sz] = {1,2,3,4,5};int *ip = arr; // 等价于 int *ip = &arr[0];int *ip2 = ip +4; //ip2指向的是arr[4];int *p = arr +sz; //此时p指向arr尾元素的下一位置,不要解引用int *p2 = arr +10;  //错误:arr只有5个元素,p2的值未定义

 和迭代器一样,两个指针相减的结果是它们之间的距离。参与运算的两个指针必须指向同一个数组当中的元素:

auto n =end (arr) - begin(arr); // n的值是5,也就是arr中元素的数量//两个指针相减的结果的类型是一种名为ptrdiff_t的标准库类型,和size_t一样,ptrdiff_t也是一种定义在cstddef头文件中的机器相关的类型。因为差值可能是负值,所有ptrdiff_t是一种带符号类型。

 两个指针只要指向同一个数组的元素,或者指向该数组尾元素的下一位置,就能利用关系运算符对其进行比较。

解引用和指针运算的交互

int ia[] = {1,2,3,4,5};int last=*(ia+4);  //last =5;

下标和指针
 如前所述,在很多情况下,使用数组的名字其实用的是一个指向数组首元素的指针。

int ia[] = {0,2,4,6,8};int i =ia[2];int *p=&ia;i = *(p+2);   //等价于i =ia[2]int *p = & a[2];int j = p[1]; //p[1]等价于*(p+1),等价于ia[3]int k = p[-2];//p[-2]表示ia[0]

 内置的下标运算符所用的索引值不是无符号类型,这一点与vector和string不同。标准库类型限定使用的下标必须是无符号类型,而内置的下标运算无此要求,上面最后一个例子很好地说明了这一点。内置的下标运算符可以处理负值,当然,结果地址必须指向原来的指针所指向同一数组中的元素或者同一数组尾元素的下一位置。

原创粉丝点击