此处的数组非顺序容器array
初始化,
使用下标访问数组时,下标定义为size_t类型。
beg 和 end 函数(注意和 顺序容器中的 beg end成员的区别)
int a[10];
int *beg = beg(a);
int *end = end(a); // 返回末尾元素的后一个位置
多维数组:
本质:数组的数组。常把第一维叫 行,第二维度叫 列。
初始化:用一个花括号初始化(全部的值放一起,逗号隔开,个数 <= 行 * 列,举例:int ia[3][4]= {1, 2, 3, 4 },显式初始化了第一行,剩下的被初始化为0),或者用多个花括号初始化(同样最外层的大括号少不了,但是里层就是一个大括号表示一行的初始化,举例:int ia[3][4]= { {1}, { 2}, {3} },显式初始化了每一行的第一个元素,剩下的被初始化为0)
对多维数组进行处理的三种方式:下标、范围for 和 指针。
a. 下标:
constexpr size_t row = 3, col=4;
int ia[ row ][ col ] ; // 二维数组未被初始化
for (size_t i = 0; i != row; i++) // 对每一行
for (size_t j = 0; j != col; j++) // 对行内每一列
ia [ i ][ j ] = i * col + j;
b. 范围 for
constexpr size_t row = 3, col=4;
int ia[ row ][ col ] ; // 二维数组未被初始化
for (auto &r : ia) // 对每一行,即外层数组的每一个元素
for (auto &c : r ) {// 对行内每一列,即内层数组的每一个元素
c = cnt;
cnt++; }
预备:程序使用数组名时,会自动将其转换成指向数组首个元素的指针。
第一个 for 遍历 ia 的每一个元素,这些元素是大小为4的数组,所以r 的类型为含有4个元素的引用。
第二个 for 遍历 r 的每一个元素,这些元素类型为整形,所以 c 的类型为整形的引用。
即使第二个for 循环里不对数组的元素进行写操作,不改变他们的值,第一个for循环 r 也要用引用的形式?为什么:
因为第一个for循环遍历 ia 的每一个元素,这些元素是大小为4 的数组,若 r 不是引用,编译器初始化 r 时会将这些数组形式的元素(像其他类型的数组一样)自动转换成指向这些数组内首元素的指针,这样得到的 r 的类型就是 int,这样第二层循环编译器试图在一个int 内遍历,这显然是不对的,
所以:要使用范围for 语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。 -- 《C++ primer》
c. 指针和多维数组
// 读取二维数组 ia [ 3 ][ 4 ]中的每个值
for ( auto p = ia; p != ia + 3; ++p){
for (auto q = *p; q != *p + 4; ++p)
cout << *q << ' ';
cout << endl;
}
预备:
int ia [ 3 ][ 4 ];
int (p)[4] = ia; // ia 被转换为指向 ia 内三个 数组 元素*的首地址,按照《C++ primer》的说法,从内往外的顺序来理解这个表达式
// (*p) 表示p 是个指针,再看右边, 可知p 是指向大小为 4 的数组的指针,再看右边,这个数组的元素的类型为 int ,这样就可以知道 p 指向含有四个整数的数组。
//
int *p[4]; // p 是整形指针的数组
有了这个基础就可以解释上面的代码了。C11的新标准,可以使用auto就能尽可能的避免在数组前面加上一个指针类型了,
即:auto p = ia(和 int (p)[4] = ia;是一样的);auto q = p; p 是指向一个含有4个整数的数组,那么p* 就是一个含有4元素的数组,所以p被自动地转换成指向该数组首元素的指针,这就解释了为什么 内层for 循环 的判别条件为q != p + 4;
附:《C++primer》习题 3-43
三种不同版本输出二维数组的元素(不能使用 类型别名 或 auto 或 decltype):
// 范围 for
cout<< "range for :" <<endl;
for(const int (&row)[4] : ia) {
for(int col : row)
cout << col << " ";
cout << endl;
}
// 普通for,使用下标
cout<< "普通for,使用下标" <<endl;
for(size_t i = 0; i != 3; ++i) {
for(size_t j = 0; j!= 4; ++j)
cout << ia[i][j]<< " ";
cout <<endl;
}
// 普通for,使用指针
cout << " 普通for,使用指针 " <<endl;
for(int(*row)[4] = ia; row != ia + 3; ++row) {
for(int *col = *row; col != *row +4; ++col)
cout << *col<<" ";
cout << endl;
}
使用类型别名替代循环控制变量的类型:
using int_array = int[4];
// 范围 for
cout<< "range for :" <<endl;
for(int_array&row : ia) {
for(int col : row)
cout << col << " ";
cout << endl;
}
// 普通for,使用下标
cout<< "普通for,使用下标" <<endl;
for(size_t i = 0; i != 3; ++i) {
for(size_t j = 0; j!= 4; ++j)
cout << ia[i][j]<< " ";
cout <<endl;
}
// 普通for,使用指针
cout << " 普通for,使用指针 " <<endl;
for( int_array *row = ia; row != ia + 3; ++row) {
for(int *col = *row; col != *row +4; ++col)
cout << *col<<" ";
cout << endl;
}
使用类型别名:
// 范围 for
cout<< "range for :" <<endl;
for(auto &row : ia) {
for(int col : row)
cout << col << " ";
cout << endl;
}
// 普通for,使用下标
cout<< "普通for,使用下标" <<endl;
for(size_t i = 0; i != 3; ++i) {
for(size_t j = 0; j!= 4; ++j)
cout << ia[i][j]<< " ";
cout <<endl;
}
// 普通for,使用指针
cout << " 普通for,使用指针 " <<endl;
for( auto *row = ia; row != ia + 3; ++row) {
for(int *col = *row; col != *row +4; ++col)
cout << *col<<" ";
cout << endl;
}
原文链接: https://www.cnblogs.com/chli/p/7587107.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/260362
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!