C++Primer 数组部分

数组是一种复合类型,与vector类似数组也是存放类型相同的对象的容器(所以不能存放引用),这些对象没有名字,需要通过其位置访问。数组本身是一个对象。

与vector不同的是数组的大小是固定的,不能随意的向数组中增加元素。

首先是数组的声明,数组的声明形如 a[d] ,其中a是数组的名字,d是数组的维度,维度必须是一个常量表达式,且必须大于0;

默认情况下,数组中的元素会被默认初始化,和内置类型的变量一样,如果在函数内部定义了某种内置类型的数组,那么默认初始化会令数组含有未定义的值。在定义数组时,必须指定数组的类型,不允许用auto关键字有初始值的列表推断类型。

在使用字符串字面值对数组初始化的时候,注意字符串字面值的结尾处还有一个空字符,这个空字符也会像被拷贝到字符数组中去。

char a1[] = "C++";                     //会添加表示字符串结束的空字符
char a2[] = {'C','+','+','\0'};        //等价于a1,含有显式的空字符

让我们来看看书中几个数组的声明:

int *ptrs[10];                         //定义了一个存放了10个指向int类型的指针,名为ptr的数组
int &refs[10] = /* ? */;               //illegal,数组中存放的是对象,而引用只是变量的别名,不是一个对象
int(*Parray)[10] = &arr;               //从内部向外理解数组的定义,首先看*Parray,这意味着Parray是一个指针,然后看右边,可知Parray指向的是一个大小为10的数组,接下来看左边,可知数组中的元素类型为int,其中arr为数组名,&为取地址运算符
int (&arrRef)[10] = arr;               //arrRef是一个绑定了一个含有10个int类型元素的数组,其中arr为数组名

与vector和string一样,数组的元素也可以通过 范围 for 语句或下标运算符来访问,数组的索引从0开始。数组的下标通常被定义为size_t类型。size_t是一种机器相关的无符号类型,它被设计得足够大以便能表示内存中任意对象的大小,在cstddef头文件中定义。

在使用数组的时候编译器一般会把他转换成指针

和其他对象一样,对数组的元素使用取地址符就能得到指向该元素的指针:

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

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

string *p2 = nums;                    //等价于 string *p2 = &nums[0]

在大多数的表达式中,使用数组类型的对象其实是使用一个指向该数组首元素的指针。(没看懂什么意思)

例如:使用数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组。

int a[10];
auto a2(a);                           //a2是一个整型指针,指向a第一个元素。等价于 auto a2(&a[0]);

当使用decltype关键字是上述转换不会发生,decltype(a)返回的类型是有10个整数构成的数组。

可以定义一个指向数组的尾后元素的指针来完成对数组的循环,但是这样极容易出错,因为尾后元素不是实际存在的,所以如果对尾指针进行解引用或者递增操作会发生不可预知的错误。

标准库函数begin和end:

begin和end这两个函数被定义在iterator头文件中,作用是返回数组首元素的指针和数组尾后元素的指针。由于数组不是类类型,因此这两个函数不是成员函数,正确的使用形式是将数组作为他们的参数

指针运算:

两指针相减的结果是他们之间的距离,参与运算的两个指针必须指向同一数组当中的元素,而该结果的类型为 定义在cstddef头文件中的ptrdiff_t类型,它是一种带符号的类型。

如果p是空指针,允许,给p加上或减去一个值为0的整型常量表达式。两个空指针也允许彼此相减,结果当然是0.(有什么用呢?)

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

int  i= a[2];
//等价于
int *p = a[];
i = *(p+2);
//
int j = p[1];                      //等价于*(p+1)
int k = p[-2];                     //等价于*(p-2)

有关C风格字符串的问题,问题焦点就是C语言中的字符串是一个元素类型char的数组,而C++中的字符串却是一个string类型,

很多string的内置操作不能用在char上。(猜的)

使用数组初始化vector对象:

只需要指明拷贝区域的首元素地址和尾后地址:

vector<int> ivec(begin(int_arr),end(int_arr));

vector<int> subVec(int_arr + 1,int_arr + 4);      //三个元素 int_arr[1]、int_arr[2]、int_arr[3]

多维数组:数组的数组

多维数组的初始化:

int a[3][4] = {
{0,1,2,3},
{4,5,6,7},
{8,9,10,11}
};

等价于:

int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

在遍历多维数组的时候要注意:在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向数组首元素的指针。

所以在下面的代码中,即使我们没有要修改数组元素的值,但是编译器在初始化row时,会自动将这些数组形式的元素转换成指向该数组内首元素的指针:

for (auto row : ia)
    for(auto col : row)


本部分留下的问题:

数组不是 类 类型?

如果p是空指针,允许,给p加上或减去一个值为0的整型常量表达式。两个空指针也允许彼此相减,结果当然是0.(有什么用呢?)



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值