字符串和数组


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

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM