数组和动态数组

这篇博客主要探讨了C++中的数组,包括数组的定义、初始化、访问和删除。详细介绍了数组作为函数参数和返回值的情况。重点讨论了数组的动态内存分配,解释了动态分配的原因和操作,提供了相关代码示例。此外,还提到了数组的sizeof运算符的使用和数组越界问题。最后,推荐了一些关于数组动态分配内存的学习资源。
摘要由CSDN通过智能技术生成

0、前言

本来想把数组的各种复习记录一下。但是我实在太懒,不想重复到处都有的东西。用的时候再百度吧。
还是记录一下,数组、数组指针和动态数组什么的,我比较爱混的问题,和一些记不住的东西。

1、数组

C++ 支持数组数据结构,它可以存储一个固定大小相同类型元素的顺序集合。

1.1、数组的定义
//type arrayName [ arraySize ];
double balance[10];
float temperature [100] ; // 100 个 float 值的数组
char letter [2 6] ;    // 26 个 char 值的数组
double size [1200] ; // 1200 个 double 值的数组
string name [10] ; // 10 个 string 对象的数组

这叫做一维数组。arraySize 必须是一个大于零的整数常量,例如,要声明一个类型为 double 的包含 10 个元素的数组 balance。
由于数组是在编译的时候定义的,不是在运行的时候决定大小的。所以arraySize 必须是常量或常量表达式。

1.2、初始化
double balance1[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
double balance2[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
balance1[4] = 50.0;

大括号 { } 之间的值的数目不能大于我们在数组声明时在方括号 [ ] 中指定的元素数目。
如果您省略掉了数组的大小,数组的大小则为初始化时元素的个数。因此,balance1和balance2相同。

1.3、访问
double salary = balance[9];
1.4、删除数组

数组分配在栈,生命周期结束,就会清理。不像动态分配的数组需要手动删除。

2、数组和函数

2.1、函数的参数是数组

传递参数是数组有如下3中形式:

void myFunction(int *param)
{
.
}

void myFunction(int param[10])
{
.
}

void myFunction(int param[])
{
.
}

这三种形式传递的都是一个指针,只是表现形式不同,而且对于数组的大小不确定,需要编程时自己自己控制。

2.2、函数的返回值是数组

函数返回数组,只有数组中函数中定义的时候才需要返回。但是局部变量定义的数组,在函数返回后就结束生命周期释放内存了。所以只有动态分配内存的数组可以返回。我们将在下面数组的动态分配中说。

最近复习看到返回static的局部变量数组这个方法。
从原理上来说,static的变量是在第一次运行时候声明的,到类的生命周期结束才结束。虽然是在函数内生命的,离开这个函数的范围后,变量是不见,但是数组 r的内存空间并没有释放。所以返回数组地址可以获得内容。(这样总总是感觉很别扭。欢迎讨论。)
测试代码如下:

int * getData( )
{
    static int  r[10];
    for (int i = 0; i < 10; ++i)
    {
        r[i] = i;
    }
    
    return r;
}

int main(int argc, const char * argv[]) {

    int * dd = getData();
    
    for (int i=0;i<10 ; i++) {
        std::cout<<dd[i]<<" ";
    }
}

3、数组的动态内存分配

3.1、数组动态内存分配的原因:

1、在静态数组定义时数量必须时常量,就是必须在编译时确定数组的长度,太不灵活。
2、静态数组分配在栈上,程序的栈内存很有限。

相对的动态数组:
1、可以在运行时候,在确定数组长度。
2、内存分配在堆上。可以自行管理数组的生命周期。

3.2、动态数组

关于动态数组的应用,下面代码十分清晰详细了。
代码来源:https://www.cnblogs.com/chengjundu/p/11039148.html

#ifndef DyArray_H
#define DyArray_H

#include <iostream>

//一维数组
void oneDimensionalArray()
{
    //定义一个长度为10的数组
    int* array = new int[10];
    //赋值
    for(int i = 0; i < 10; i++)
    {
        array[i] = i*2;
    }
    //打印
    for(int i = 0; i < 10; i++)
    {
        std::cout << i << " : " << array[i] << std::endl;
    }
    //释放内存
    delete[] array;
}

//二维数组
void twoDimensionalArray()
{
    //定义一个2*10的二维数组
    int** array = new int*[2];
    for(int i = 0; i < 2; i++)
    {
        array[i] = new int[10];
    }
    //赋值
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            array[i][j] = i*10 + j;
        }
    }
    //打印
    for(int i = 0; i < 2; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            std::cout << "(" << i << ", " << j << ")" << array[i][j] << std::endl;
        }
    }
    //释放内存
    for(int i = 0; i < 2; i++)
    {
        delete[] array[i];
    }
    
    delete[] array;
}

//三维数组
void threeDimensionalArray()
{
    //定义一个3*10*20的数组
    int*** array = new int** [3];
    
    for(int i = 0; i < 3; i++)
    {
        array[i] = new int*[10];
        for(int j = 0; j < 10; j++)
        {
            array[i][j] = new int[20];
        }
    }
    //赋值
    for (int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            for(int k = 0; k < 20; k++)
            {
                array[i][j][k] = i*100 + j*10 + k;
            }
        }
    }
    //打印
    for (int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            for(int k = 0; k < 20; k++)
            {
                char str[64];
                sprintf(str, "(%d, %d, %d): ", i, j, k);
                std::cout << str << array[i][j][k] <<std::endl;
            }
        }
    }
    //释放内存
    for (int i = 0; i < 3; i++)
    {
        for(int j = 0; j < 10; j++)
        {
            delete[] array[i][j];
        }
    }
    for (int i = 0; i < 3; i++)
    {
        delete[] array[i];
    }
    
    delete[] array;
    
}


#endif /* DyArray_H */

4、其它

4.1、sizeof

对静态数组名进行sizeof运算时,结果是整个数组占用空间的大小;
因此可以用sizeof(数组名)/sizeof(*数组名)来获取数组的长度。

 int a[5]; 
 int s1 = sizeof(a);	// 4*5=20
 int s2 = sizeof(*a);	// 4

因为整个数组共占20字节,首个元素(int型)占4字节。

int * a = new int[7];
int s1 = sizeof(a);	// 4
int s2 = sizeof(b);	// 4

因为地址位数为4字节,int型也占4字节。

静态数组作为函数参数时,在函数内对数组名进行sizeof运算,结果为4,因为此时数组名代表的指针即一个地址,占用4个字节的内存(因为在传递数组名的参数时,编译器对数组的长度不做检查)。对动态数组的函数名,无论何时进行sizeof运算,得到的结果都是4.

4.2、数组越界

静态数组和动态数组最经常饭的错误,就是数组越界。现象是崩溃。

new出来的数组都调用默认构造函数对数组对象进行初始化了。如果是int这里原始的数据类型,需要在new后面添加(),才会进行初始化。代码如下:

int * aa = new int[10]();

ps: 参考文章列表:

https://www.runoob.com/cplusplus/cpp-arrays.html
https://www.runoob.com/cplusplus/cpp-multi-dimensional-arrays.html
https://www.runoob.com/cplusplus/cpp-pointer-to-an-array.html
https://www.runoob.com/cplusplus/cpp-passing-arrays-to-functions.html
https://www.runoob.com/cplusplus/cpp-return-arrays-from-function.html

http://c.biancheng.net/view/1414.html
详细,完整,图示清晰。讲了数组在内存中的分配方式。适合初学者。
最后,还深入讲解了数组越界的形成。

动态数组相关参考文章:
https://www.jianshu.com/p/ef413611c4af
https://blog.csdn.net/summer00072/article/details/80609427

https://www.cnblogs.com/chengjundu/p/11039148.html
数组动态分配内存。
定义,分配内存,初始化,访问和删除。代码清晰。用于快速查询

https://www.cnblogs.com/lidabo/p/9664396.html
数组的动态内存分配的 细节问题,说的很好。

https://blog.csdn.net/manchengpiaoxue/article/details/83145476
有些不一样的东西。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值