字符串和数组

此处的数组非顺序容器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

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月14日 下午1:26
下一篇 2023年2月14日 下午1:28

相关推荐