• C++数组概述


    C++数组概述


    基本概念

    1. 数组是固定大小的一种复合类型

    • 因为数组是固定大小,所以在编译期间就决定了基大小
    • 数组的内存是连续(无论是一维数组还是多维数组)

    2. 数组的特性

    • 数组之间不允许拷贝和赋值
    • 数组名是常指针

    数组的操作

    1. 数组的初始化

    • 数组定义时不初始化,则会被初始化为未初始化值
    int nArr[4]; // 当数组为全局变量时,未初始化值默认为0;当数组为局部变量时,则其值在Debug下为0xccccccc,Release下为随机值
    
    • 大括号显式初始化
    int nArr1[4] = {1, 2, 3, 4};
    int nArr2[4] = {1, 2, 3};   // 第4值默认为0
    int nArr3[] = {1, 2, 3, 4}; // 编译器在编译阶段推断数组维数为4 
    int nArr4[][4] = {1, 2, 3, 4, 5, 6, 7, 8}; // 数组最高维可以在编译阶段推导出为2
    int nArr5[][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}}; // 数组最高维可以在编译阶段推导出为2
    int nArr6[][4] = {{1}, {5}}; // 数组最高维可以在编译阶段推导出为2,剩下的默认为0
    int nArr7[2][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}}; // 数组大小与赋值必须匹配
    
    • 字符数组
    char szArr[] = "abcd"; // 编译器在编译阶段推断数组维数为5 
    

    2. 数组的大小

    int nArr1[4] = {0};         // sizeof(nArr1)为16,因为nArr1是int[4]类型
    int nArr2[3][4] = {0};      // sizeof(nArr2)为48,因为nArr2是int[3][4]类型
    

    3. 数组与引用

    int nArr6[][4] = {{1}, {2}, {3}}; // 数组最高维可以在编译阶段推导出为2,剩下的默认为0
    int (&nArr7)[4] = nArr6[1];       // nArr7即是nArr6[2]的引用
    int nArr8[4] = {0};
    int (&nArr9)[4] = nArr8;          // nArr9即是nArr8的引用
    

    4. 数组与指针

    	int nArr1[4] = {0};
    	int nArr2[3][4] = {0};
    	int *p1 = nArr1;      
    	int *p2 = nArr2[1];
    	int *p3 = &nArr2[1][0];     // p2,p3是相等的
    	int (*p4)[4] = nArr2;       // 此处的数组名nArr2退化为指针,p4是指针,指向int [4]类型数组首地址
    	int (*p5)[4] = &nArr2[0];   // p4,p5也是相等的
    	int *p6[4]; // p6是数组,存放4个int类型指针。sizeof(p6)=16
    	int* p7[4]; // 因为[]的优先级最高,所以p6,p7是相同的
    

    5. 数组类型别名

    typedef int intArray[4];
    typedef int int2DArray[3][4];
    intArray arr1 = {0};
    int arr2[4] = {0};
    // arr1,arr2是等价的
    int2DArray arr3 = {0};
    int arr4[3][4] = {0};
    // arr3,arr4是等价的
    

    6. 数组作为函数参数

    -值与数组 因为数组不能拷贝,所以数组理论上不能作为值传递的形参。但事实上,我们有看到直接用数组作为参数值传递的,这明显违背数组拷贝的原理。如下段代码,其实是特殊情况,arr其实并不是数组类型,arr在作为形参时已经自动退化成指针了。

    void Test(int arr[4])
    {
        *arr = 4;
        int nSize = sizeof(arr); // 因为arr退化成指针,所以nSize=4
    }
    void Test1(int arr[])
    {
        int nSize = sizeof(arr); // 因为arr退化成指针,所以arr[]的维数写不写无影响
    }
    void Test2(int arr[][4])
    {
     int nSize = sizeof(arr); // 因为arr退化成指针,所以arr[]的维数写不写无影响,nSize=4
    }
    void Test3(int (*arr)[4])
    {
     int nSize = sizeof(arr); // Test3和Test4是等价的
    }
    
    • 引用与数组
      数组类型的引用是合法的,引用类型的数组是非法的。
    void Test(int (&arr)[4])
    {
        int nSize = sizeof(arr); // 因为arr是int [4]类型,所以nSize=20,此处维数不能省
    }
    void Test1(int &arr[4]) // Error,arrays of references are illegal
    {
    }
    
    • 指针与数组
    void Test(int (*arr)[4])
    {
        int nSize = sizeof(arr); // arr是指针,指向int [4]首地址
    }
    void Test1(int* arr[4])
    {
        int nSize = sizeof(arr); // arr看起来是int* [4]类型,是数组,但是数组不能拷贝,所以退化成指针
    }
    void Test2(int* arr[])
    {
        int nSize = sizeof(arr); // arr[]退化成指针,Test2和Test1造价,nSize=4
    }
    

    7. 数组作为函数返回值

    • 返回值 因为返回值也会生成拷贝,所以与数组不能拷贝相违背,所以数组值不能作为函数返回。
    • 返回引用
      引用的数组是非法的,所以只能返回数组的引用
    int (&Test)() [4]  // 返回的值优先引用,然后因为数组的引用,所以数组在引用后
    {
        int nArr[4] = {1, 2, 3, 4};
        return nArr;
    }
    int (&nTemp)[4] = Test();
    // 上面返回引用的方式难理解,我们可以换一种方式
    typedef int intArray[4];
    intArray& Test() // 利用typdef简单数组类型
    {
        int nArr[4] = {1, 2, 3, 4};
        return nArr;
    }
    intArray& nTemp = Test();
    // C++11引用了类型推导,可以用下面形式
    int nArr[4] = {0, 1, 2, 3};
    decltype(nArr)& Test23()
    {
    	return nArr;
    }
    
    • 返回指针
      因为数组不能拷贝,所以不能返回指针类型的数组(int* [4]),但可以返回指向数组的指针。
    int nArr[3][4] = {{4}, {1, 5}, {2}};
    int (*Test())[4]
    {
    	int (*pArr)[4] = nArr;
    	return pArr;
    }
    int (*pArr)[4] = Test();
    // 用typedef,C++11也可以用decltype(代码略)
    typedef int intArray[4];
    int nArr[3][4] = {{4}, {1, 5}, {2}};
    intArray* Test()
    {
    	int (*pArr)[4] = nArr;
    	return pArr;
    }
    intArray* pArr = Test();
    

    8. 数组与vector

    • 异同
    1. 相同点,数组与vector的内存都是连续的。
    2. 不同点,数组是固定大小,而vector是动态大小。
    • 相互转化
      数组可以看作是特殊的vector,所以一些适用于vector的算法,如sort,unique都是可以用于数组的。
    int nArr[5] = {4, 3, 2, 1, 5}; 
    sort(nArr, nArr+_countfof(nArr));
    vector<int> vInt(nArr, nArr+_countfof(nArr));
    // 因为vector内存是连续的,所以可以直接拷贝内存。
    memcpy(nArr, &vInt[0], vInt.size()*sizeof(int));
    
  • 相关阅读:
    设计模式desine pattern梳理
    system desing 系统设计(二): 数据库sharding和Consistent Hashing算法原理
    system desing 系统设计(一): 数据库sql和NoSql的选择
    system desing 系统设计(三): 分布式文件系统distributed file system设计原理
    system desing 系统设计(四):网站API和短网址short url的生成
    HTML 基础知识总结
    Linux 基础知识总结
    CSS 基础知识总结
    Codeforces Round #821 (Div. 2)
    AtCoder Beginner Contest 271
  • 原文地址:https://www.cnblogs.com/feihe0755/p/7081674.html
Copyright © 2020-2023  润新知