c/c++数组详解

 数组是一种复合类型。由数组的类型、名字、维度构成。其中维度说明了数组中元素的个数,必须大于0,维度在编译的时候一定是可知的,所以维度必须是一个常量表达式。

unsigned cnt = 42;   //不是常量表达式
constexpr unsigned cnt1 = 42;  /*是一个常量表达式(声明为constexpr的变量一定是一个常量,必须用常量表达式来初始化)*/
int arr[10]; //含有10个整数的数组
int* parr[cnt1]; // 含有42个整数指针的数组
string bad[cnt]; //错误的,因为cnt不是一个常量表达式
string strs[get_size()];  // 当 get_size()是constexpr时才正确,否则是错误的

在定义数组的时候必须指定数组的类型,不可以用auto关键字推导。不存在引用的数组。

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

显式初始化数组:

	const unsigned sy = 3;
	int a1[sy] = { 0,1,2 }; //维度为3的数组,它有3个值分别 为:0,1,2
	int a2[] = { 0,1,2 };    //维度是3,可以像这样写,它的空间大小就是由你赋值的多少决定
	int a3[4] = { 0,1,2 };  //等价于 a3 [] ={ 0,1,2,0 };后面未初始化的值被默认初始化为0
	string a4[3] = { "hi","sy" }; //等价于 a4[] = { "hi","sy", "" }
	int a5[2] = { 0,1,2 }; //错误,初始值过多,超出数组空间的大小

当我们在实际写程序的时候,一定要注意下标越界的问题,这个问题很多时候容易被忽视,又不太容易被发现。

在标准库当中数组不允许拷贝和赋值:

int a[] = {0,1,2};
int a1[] = a ;//错误
a2 = a ;//错误

复杂的数组声明:

	int arr[10] = { 0,1,2,3,4,5 };
	int* ptrs[10]; //ptrs是含有10个整形指针的数组
	int& sy[10];  //错误:不存在引用的数组
	int(*parr)[10] = &arr; //parr指向一个含有10个整数的数组
	int(&parr1)[10] = arr; //parr1 引用一个含有10个整数的数组

修饰符的数量没有特殊限制:

int *( &parr ) [10] = arr; //parr是数组的引用,该数组含有10个指针

我们要理解复杂数组的声明,最好的办法就是从数组的名字开始由内向外的顺序阅读。

访问数组元素:数组可以用范围for或下标运算符访问,要记住一点就是数组下标是从0开始,不要越界。

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


	int arr[ ] = { 0,1,2,3,4,5,6,7,8 };
	for (size_t i : arr) //size_t 那里最好使用auto自动推导
	{
		cout << i << endl;
	}

指针和数组

我们可以使用取地址符来获取某个对象的指针,取地址符可以作用于任何对象。对数组使用下标运算符获取的是数组的对象,而使用取地址符就是获取这个元素的指针:

	string  nums[] = { "one ", "two " , "three" };
	string* p = &nums[0]; 
	string* p1 = nums; //这个等价于	string* p1 = &nums[0]; 直接使用数组的名字,数组的名字就是代表指向数组第一个元素的指针
	cout << *nums << endl;//解引用数组的首指针得到数组的第一个元素
	cout << nums << endl; //输出数组首指针的地址

当我们使用数组作为 auto 变量的初始值的时候,推导得到的类型是指针并不是数组:

int ia [] = {0,1,2,3};
auto ia1(ia); //ia1是一个整形指针,指向ia的第一个元素
ia1 = 41 ; //错误,上面的推导是一个指针类型,不能用整形值给指针赋值
//上面的推导编译器推导的时候是这样的形式: auto ia1(&ia[0]);

当我们使用 decltype 关键字 (选择并返回操作数的类型) 的时候,上面的转换就不会发生:

	int ia[] = { 0,1,2,3 };
	decltype(ia)  ia1; //由decltype返回的类型来定义ia1,所有ia1是一个维度为4的整数数组
	ia1[1] = 999; //对数组ia1的第二个元素进行赋值,下标是从0开始

指针也是迭代器,也有迭代器的操作:

int arr[10] = { 1,2,3,4,5,6,7,8,9 };
	int* p = arr;
	for (size_t i = 0; i < sizeof(arr)/4; i++)
	{
		cout << *p << "    ";
		p++;
	}

标准库函数 begin 和 end :

C++11新引入了两个名为 begin 和 end 的函数,把数组作为它们的参数,begin负责返回数组的首元素的指针, 而end 负责返回 数组尾元素的下一个位置的指针,符合左闭右开原则 。它们被 定义在 iterator 头文件中。

int arr[10] = { 1,2,3,4,5,6,7,8,9 };
	int* Begin_ = begin(arr);
	int* End_ = end(arr);
	while (Begin_ != End_)
	{
		cout << *(Begin_) << "    ";
		Begin_++;
	}

使用这两个库函数的时候注意的是:尾指针不能解引用和递增操作

两个指针想减的结果就是它们之间的距离,参与运算的指针必须指向同一个数组中的元素,它们想减的结果的类型是一种名为  ptrdiff_t 的标准库类型,它也被定义在 cstddef 头文件中,它是一种带符号的类型,它可正可负。

允许两个空指针想减,但不允许它们相加:

	int* p = nullptr;
	int* i = nullptr;
	cout << p -i << endl; //结果为0

下标和指针:

标准库类型限定了使用的下标必须是无符号类型,但是内置的下标运算符没有这个限制。

例如:

	int ia[] = { 0,1,2,3,4,5 };
	int* p = &ia[2]; //p指向索引为2的元素
	int j = p[1]; //p[1] 等价于 *(p+1) ,也就是 ia[3] 表示的那个元素
	int k = p[-2]; //p[-2 ] 是 ia[0] 表示的那个元素

数组还有二维数据及二维以上的数组。不过维度太多比较麻烦,一般来说二维就够我们使用了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

syhk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值