zoukankan      html  css  js  c++  java
  • 《c++ primer》3.5 array 小结

    array的长度是静态的,即在编译阶段就已经确定。没有 vector 灵活,但性能一般更强。

    1. 声明

    维数必须是一个 constant expression,另外数组中每个单元必须指明类型(不能用auto),必须是对象,不能是别名(reference)。

    1 int arr[10];
    2 int *parr[sz]; // 42 个整数指针
    3 string str[ get_size() ]; // 如果 get_size() 返还常数表达式就ok,否则错误

    2. 初始化

    int ia1[3] = {0,1,2};
    int ia1[] = {0,1,2}; // 自动确定维数为3
    int ia1[5] = {0,1,2}; // 自动将后2个元素初始化为0
    string a4[3] = {"hi", "bye"}; //自动将最后一个元素初始化为""

    3. 字符数组

    字符数组多一个隐含的元素 在末尾,作为结束的标志。

    char a1[] = {'C', '+', '+'};//长度实际为4,自动增加 ''
    char a4[6] = "Daniel"; //错误,没有空间给隐含的 ''

    4. 指向数组的指针

    int * ptrs[10]; // ptrs 是10个整数指针构成的数组
    int (*Parray) [10] = & arr; // Parray 是指向数组arr 的指针,arr由10个整型构成
    int (&arrRef) [10] = arr; // arrRef 是数组 arr 的别名,arr 由10个整型构成
    int * (&arry) [10] = ptrs; // ptrs 是 10 个指向整型的指针构成的数组,arry 是它的别名

    5. 引用数组的单元

    可以用下标,也可以用 range for。下标范围是 0, 1, n-1,其中n为维数。下标应为 size_t 类型,size_t 无符号,可以足够大,在 cstddef 头文件中。

    如果要遍历所有单元,用 range for 是更好的选择,

    unsigned scores[11] = {};
    for( auto i: scores)
        cout<< i << " ";
    cout<<endl;

    6. 指针与数组

    实际上,数组就是用指针实现的。

    string num[] = {"one", "two", "three"};// num 也是一个指针,指向第一个元素

    7. begin, end 函数

    指针是一种迭代器,但数组不是类,所以没有成员函数 begin(), end(),于是 library 提供了 begin(arr), end(arr) 函数

    int *pbeg = begin(arr), *pend = end(arr); 
    while( pbeg != pend && *pbeg >=0) // 寻找整数数组中第一个负整数
        ++pbeg;

    不可以dereference 或者增加 end(arr)指针,因为 end(arr) 指向的是数组外的地址。

    因为指针是迭代器,所以其他迭代器的操作也适用,比如加上一个整数(若指向数组外,除了end(arr)以外的值是错误的),两个指针相减,比大小。

    下标符号[] 可以用在任何指针上,只要得到的元素再数组内。

    int ia[] = {0,2,4,6,8};
    int *p = & ia[2]; // p 指向元素4
    int k = p[-2]; // k  = ia[0] = 0

    所以下标可以是负整数,只要得到的元素仍在数组内就行。

     8. C风格的字符串

     我记得谭浩强老师的C++教程就是沿用的C风格的字符串,它是如下表示的:

    char a[80] = "hahaha"; // 自动用''结束,即 a[6]=''

    默认用 '' 表示字符串内容的结束,数组长度必须大于等于字符串长度+1。

    library提供了一些函数对这种风格的字符串进行操作

    strlen(p)            字符串p的长度,不包括''即null字符
    strcmp(p1,p2)    比较两个字符串,①比较长度,②按字典顺序比较字符
    strcat(p1,p2)        将 p2 的内容追加到 p1,然后返回 p1
    strcpy(p1, p2)        将 p2 的内容赋值给 p1,返回 p1

    上面这些函数都不能保证字符数组长度够用,字符数组长度够用必须由程序员来手动保证。

    所以很容易发生错误。c++提倡使用 vector 和 string类型,而不是 数组 和 C风格的字符串。但有些代码是用后者写的,需要跟那些代码打交道,所以c++的 library 提供了办法处理这些过时的对象。

    const char * str = s.c_str(); //  string 类 s 的内容变成一个C风格的字符数组并返还首字符的指针

    可以调用 string 的成员函数 c_str,返还一个C风格字符数组的指针,但如果此后改变了 string s,这个指针可能会出现错误,所以改变之前先 copy str[] 里面的内容。

    9. 用数组来初始化vector

    int int_arr[] = {0, 1, 2, 3, 4, 5};
    vector<int> ivec( begin(int_arr), end(int_arr) ); // ivec 的内容为 arr 中的所有成员
    vector<int> subVec( int_arr+1, int_arr+4 ); // subVec 的内容为 1,2,3,4

    10. 多维数组

    没有多维数组,多维数组实则是基本单元是数组的数组。

    int ia[3][4] = {{0,1,2,3},{4,5,6,7},{8,9,10,11}};
    int ia[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11}; //编译器自动分行
    int ia[3][4] = {0,3,6,9}; //第一行元素为 0,3,6,9,其他元素赋0 (value-initialized)

    可用 range for 来遍历多维数组

    size_t cnt = 0;
    for( auto &row : ia)
        for( auto &col : row){
            col = cnt;
            cnt++;
        }

    这里 row, col 必须用别名,否则,ia 的成员是指向 4元素数组 的指针,row  会是一个这样的指针,但没有下一步单元,所以内层循环会错误。

    所以,用 range for 来遍历多维数组时,除了内层以外,其他各层的循环变量都必须是别名。所以全用别名就完事了。

  • 相关阅读:
    flex学习小结
    Frameset框架
    表格的增删改
    【实践】用 js 封装java shuffle函数(打乱数组下标方法)
    【实践】js封装 jq siblings 方法
    【笔记】js原生方法 在元素外部或内部实现添加元素功能(类似jq 的 insert 和 append)
    【实践】js实现windows系统日历
    【实践】用for-in 循环实现三联联动
    【笔记】js Array.prototype.slice.call(arguments) 将函数的参数转换为数组方法的见解
    【笔记】js Function类型 内部方法callee
  • 原文地址:https://www.cnblogs.com/luyi07/p/12688673.html
Copyright © 2011-2022 走看看