3.5.1 数组定义和访问
数组:复合类型
声明形式 数组名称 [元素个数] 例,Arr[N],N必须是常量表达式
unsigned cnt =42; constexpr unsigned int sz =1;//常量表达式 int arr[10]; int* ptr[sz]; // std::string bad[cnt]; 错误,cnt不是常量表达式
不存在引用数组,可以使用列表初始化,但必须指定数组类型,不允许使用 auto
constexpr unsigned sz =3;//常量表达式 int arr1[sz] = { 0, 1, 2 }; int arr2[] = { 0, 1, 2 }; //自动推断元素个数为3 int arr3[5] = { 0, 1, 2 };//等价 { 0, 1, 2 ,0 ,0 } std::string arr4[3] = {"hi“ , "bye"};//等价 {"hi" , "bye" , ""}int arr5[2] = { 0, 1, 2 }; //错误,初始值过多
字符数组特殊性
字符串默认结尾是空字符
char a1[] = { 'C', '+', '+' };//列表初始化,没有空字符 char a2[] = { 'C', '+', '+', '\0' };//列表初始化,含有显示的空字符 char a3[] ="C++";//含有空字符 const char a4[6] ="Danial";//错误,没有空间存放空字符
不允许拷贝和赋值
int a[] = { 0, 1, 2 }; //int a2[] = a;//初始化时不允许拷贝赋值
理解复杂的数组声明
【】优先级高于*
int *ptrs[10];//含有十个整型指针的数组 int&refs[10];//错误,不存在引用数组 int(*parray)[10];//指向一个含有十个整数的数组 int(&parray)[10] = arr;//引用一个含有十个整数的数组 int*(&arry)[10] = ptrs;//数组的引用,该数组包含十个整型指针
3.5.2 指针和数组,C风格字符串
指针和数组
编译器一般会把数组转为指针
std::string nums[] = { "one", "two", "three" }; std::string* p1 = &nums[0];//p指向nums的第一个元素 std::string* p2 = nums;//等价于p2 = &nums[0] int arr1[] = { 0, 1, 2, 4, 5 };//arr1是含有5个整数的数组 auto arr2(arr1);//arr2是一个整型指针,指向arr1的第一个元素 arr2 =42;//错误,arr2是一个指针 //当使用decltype时,不会出现上述转换 decltype(arr1) arr3 = { 0, 1, 2 }; arr3 = arr2;//错误,不能把整型指针赋值给数组 arr3[0] =-1;
指针也是迭代器
这种方式可得到尾后指针,易错故不推荐
int arr[] = { 0, 1, 2 }; int *p = arr; ++p;//p指向了arr[1] int* p1 = &arr[3];//指向arr尾元素的下一个位置 for (int *b = arr; b != p1; ++b){ std::cout << *b << std::endl; }
/* 寻找第一个负数 */ int arr1[] = { 0, 1, 2, 3, 4 }; int* beg = std::begin(arr1); int* end = std::end(arr1); while (beg != end && beg>0){ ++beg; } if (beg != end){ std::cout << *beg << std::endl; }
解引用和指针运算交互
int arr1[] = { 0, 1, 2 }; int last = *(arr1 +2);//last =2last = *arr1 +4;//last =4;
下标和指针
标准库类型限定使用下标不能为负,但内置类型无此要求
数组(内置) string,vector(STL 标准库)
int arr1[] = { 0, 1, 2, 3, 4}; int i = arr1[2];//与下面两条等价,充分理解 int *p = arr1; i = *(p +2); int *p1 = &arr1[3]; int j = p1[1];//等于 *(p1+1) int k = p1[-2];//等于 *(p1-2)
C风格字符串
C 风格字符串不是一种类型,而是一种约定俗成的写法
C 风格字符串的处理函数定义在 cstring 头文件中
作为参数的字符串,必须以空字符结束
#include<cstring>char str1[] = { 'C', '+', '+' };//必须以空字符结尾,已修复 std::cout << strlen(str1) << std::endl; std::string s1 ="A string example"; std::string s2 ="A different string"; if (s1 < s2) {//false 利用字符在字典顺序比较 std::cout << "s1 len 小于 s2 len " << std::endl; } const char* cstr1 ="A string example"; const char* cstr2 ="A different string"; if (cstr1 < cstr2) {//true 比较数组的size std::cout << "cstr1 len 小于 cstr2 len " << std::endl; } if (strcmp(cstr1, cstr2)<0){//和上面两个string比较一样 std::cout << "cstr1 len 大于 cstr2 len " << std::endl; }
与旧代码的接口
std::string s1("Hello World"); char* c_s2 = s1; //错误,不能将string对象赋值给char* const char* c_s3 = s1.c_str();//正确,将string转换c字符串
若后续改变了 s1 的值,那么 c_str 返回的数组将失效
//使用数组初始化 vector 对象 int int_arr[] = { 0, 1, 2, 3 }; std::vector<int> vec1(std::begin(int_arr), std::end(int_arr));//{ 0, 1, 2, 3 } std::vector<int> vec1(int_arr+1, int_arr+3);//{1,2,3}
3.6 多维数组
多维数组:严格来讲 C++ 没有多维数组,C++的多维数组是靠数组的数组实现的
int arr[3][4];//大小为3的数组,每个元素是含有4个整数的数组 int arr[10][20][30] = { 0 };//将所有元素初始化为0
初始化
一个括号即为一行
//允许使用花括号初始化多维数组 int arr2[2][2] = { { 0, 1}, { 2, 3} }; int arr3[2][2] = { 0, 1, 2, 3 }; int arr3[2][2] = { { 0 }, { 2 } };//0,0,2.0 int arr3[2][2] = { 0, 2 }; //0,2,0,0
下标引用
允许数组元素本身就是数组
//用arr1的首元素给arr0最后一行的最后一个元素赋值 arr0[3][4] = arr1[0][0][0]; /* 给数组元素初始化 */ constexpr size_t rowCnt =3, colCnt =4; int arr4[rowCnt][colCnt];//12个未初始化的元素 for (size_t i =0; i < rowCnt; ++i){ for (size_t j =0; j < colCnt; ++j){ arr4[i][j] = i * rowCnt + colCnt; } } /* 将数组元素改为 0-12*/ size_t cnt =0; for (auto& row : arr4){ for (auto& col : row){ col = cnt; ++cnt; } } //使用&可有效避免 取出的数组被编译器自动转为指针 for (auto row : arr4) for (auto col : row)//报错 int* row没有begin函数
指针和多维数组
两种形式
int arr0[3][4] = { {0,1,2,3}, {4,5,6,7}, {8,9,10,11} };//大小为3的数组,每个元素是含有4个整数的数组 //定义int arr0[3][4]; // arr0类型 int(*)[4] arr0[0]类型 int* int(*p)[4] = arr0;//等同于 int(*p)[4] = &arr0[0]; /* 输出arr0每个元素值 两种形式 */ for (auto p = arr0; p != arr0 +3; ++p){ for (auto q = *p; q != *p +4; ++q){ std::cout << *q << " "; } std::cout << std::endl; } for (auto p = std::begin(arr0); p != std::end(arr0); ++p){ for (auto q = std::begin(*p); q != std::end(*p); ++q){ std::cout << *q << " "; } std::cout << std::endl; }
类型别名简化多维数组的指针
using int_array = int[4];//typedef int int_array[4] for (int_array *p = arr0; p != arr0 +3; ++p){ for (int *q = *p; q != *p +4; ++q){ std::cout << *q << " "; } std::cout << std::endl; }
附 思维导图