What & How & Why

差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录前一修订版
后一修订版
前一修订版
后一修订版两侧同时换到之后的修订记录
cs:programming:cpp:courses:cpp_basic_deep:chpt_3 [2024/04/17 10:49] – [遍历] codingharecs:programming:cpp:courses:cpp_basic_deep:chpt_3 [2024/04/18 03:31] – [使用类型别名声明多维数组的指针] codinghare
行 266: 行 266:
 } }
 </code> </code>
-===C 字符串===+==C 字符串== 
 +  * 本质是数组 
 +  * 有额外的函数来支持该数组 ''<cstring>'' 
 +====多维数组==== 
 +  * 本质上是元素为数组的数组 
 +  * 在内存中是连续排列的,但按照元素的个数分组 
 +  * 二位数组类似**行优先**矩阵,左边是行,右边是列 
 +===多维数组的理解=== 
 +<code cpp> 
 +// 从左到右看 
 +// (x[3]) 是元素,元素类型为 Int[4] 
 +int x[3][4];  
 +// (y[3]) 是元素,元素类型为 int[4][5] 
 +Int y[3][4][5]; 
 +</code> 
 +{{ :cs:programming:cpp:cpp_primer:mult_array.svg?250 |}} 
 +===多维数组的初始化=== 
 +  * 默认初始化:遵从C++ 的默认初始化 
 +  * 聚合初始化: 
 +<code cpp> 
 +//由于在内存中是连续的,因此可以使用 list 初始化 
 +//初始值不够的所有元素都会进行默认初始化 
 +//按位初始化 
 +//1,2,3,4,0,0,0,0,0,0,0,0,
 +int x[3][4] = {1,2,3,4}; 
 +//分组初始化 
 +int y[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 
 +//分组初始化的默认初始化处于分组内部 
 +int z[3][4] = {{1,2,3}, {4,5,6,7}, {8,9,10,11}}; 
 +//输出 0 
 +std::cout << z[0][3]; 
 +//输出 4 
 +std::cout << z[1][0]; 
 +//如果需要自动推断,必须指定元素的类型 
 +//只能省略最高位 
 +int a[][] = {1,2,3,4}; // error 
 +int a[][] = {{1,2,3,4}}; // error  
 +int a[][4] = {1,2,3,4}; // int[1][4] 
 +</code> 
 +===多维数组的遍历=== 
 +  * 多维数组遍历需要多重循环 
 +<code cpp> 
 +int x [3][4] = {{1,2,3,4}, {5,6,7,8}, {9,10,11,12}}; 
 + 
 +//range for 
 +//注意所有外层的 auto 都需要以引用的方式将数组类型传递给内层循环 
 +//否则,内层循环只会得到一个指向外层数组的指针 
 +//内层循环中 range for 需要使用数组的头指针作为起点,头指针 + 内层数组的长度作为终点进行循环 
 +//如果传入的是指针,长度信息丢失,那么将无法进行循环 
 +for (auto &row : x) 
 +
 +    for (auto col : row) 
 +    { 
 +        std::cout << col << " "; 
 +    } 
 +    std::cout << std::endl; 
 +
 + 
 +//while loop 
 +//注意 std::size() 的参数不同 
 +//遍历的顺序:x[0][0-3], x[1][1-3], x[2][1-3]。 
 +//推荐行优先遍历,可以减少 cache miss。 
 +size_t outter = 0; 
 +while (outter < std::size(x)) 
 +
 +    size_t inner = 0; 
 +    while (inner < std::size(x[inner])) 
 +    { 
 +        std::cout << x[outter][inner] <<" "; 
 +        inner++; 
 +    } 
 +    outter++; 
 +    std::cout << std::endl;  
 +
 +//纯指针遍历 
 +//与之前相同,cbegin 和 cend 需要数组而不是指针,因此内循环需要解引用 
 +auto OutterP = std::cbegin(x); 
 +while (OutterP != std::cend(x)) 
 +
 +    auto InnerP = std::cbegin(*OutterP); 
 +    { 
 +        while(InnerP != std::cend(*OutterP)) 
 +        { 
 +            std::cout << *InnerP << " "; 
 +            InnerP++; 
 +        } 
 +        std::cout << std::endl; 
 +    } 
 +    OutterP++; 
 +
 +</code> 
 + 
 +===多维数组与指针=== 
 +  * 多维数组也可以转化为指针,但只有最高维会进行转换 
 +    * 对于外围数组,如果指针要有意义,其指向的单位一定是外围数组的元素 
 +    * 比如下面的例子,外围数组有3个元素,如果移动指针 ''x+1'',则移动的单位实际上是一个包含 4 个 int 的数组 
 +<code cpp> 
 +int x[3][4]; 
 +// ptr int(*)[4] 
 +auto ptr = x; 
 +//ptr2 int(*)[4][5] 
 +int y[3][4][5]; 
 +auto ptr2 = y; 
 +</code> 
 +==使用类型别名声明多维数组的指针== 
 +<code cpp> 
 +using A2 = Int[4][5]; 
 +int x[3][4][5]; 
 +A2* ptr = x; //x 指向 int[4][5] 
 +</code> 
 +注意类型别名会改变维度的优先级: 
 +<code cpp> 
 +using A = int[4]; 
 +//如果这里使用 A 定义数组,那么结果会是 [4][3] 而不是 [3][4] 
 +A z2[3]; //等价与 int z2[4][3]; 
 +</code> 
 +====Vector====