c++在堆区中创建数组的一些注意事项

Q1:我们为什么好端端的不在栈中创建数组,偏要跑到堆区中哪?

R1:栈中的空间是有限的,在面对一些长度很大的数组的时候,会有力不从心的感觉,所以我们选择了在堆区中。

 

1.写法

 

1.1堆区创建一维数组的写法

类型名 * 指针名=new 类型名[数组长度]

eg:  int *p=new int[10]

这就表示我们在堆区中创建了个int类型的一维数组,长度是10,并且用int类型的指针指向他来便于我们后期维护。

注意:前后类型最好一致,或者可以转换。如果前面是string,后面是int这显然不行。

 1.2堆区创建二维数组的写法

创建方法一:总感觉这个方法是在为了创建而创建,使用起来并不方便,也可能是我还没找到正确的打开方式。

类型名 (*指针名)[列数]=new 类型名[行数][列数]

eg:int (*p)[5]=new int[10][5];   这就表示我们在堆区创建了一个十行五列的int类型数组,但是这里仅仅是定义了,还没有赋值,不能直接用。

注意:1.括号很重要,千万别忘了,很容易错写成int *p[10]=new int[10][5];  这两个意思是完全不同的,下边这个连编译都通不过,毫无逻辑可言。

           2.这两个位置的数字必须相同。

 创建方法二:new/delete

int **Array = new int *[ArrayRow];
for (int i = 0; i < ArrayRow; i++)
{
    Array[i] = new int[ArrayCol]();                            // 初始化 0
}

for(i = 0; i < ArrayRow; i++)                                  // 释放内存
{  
    delete[] Array[i];  
}   
delete[] Array;  
 

创建方法三:

malloc/free:

int **Array = (int**)malloc(ArrayRow * sizeof(int *));        // 先行
for (int i = 0; i < ArrayRow; i++)
{
    Array[i] = (int*)malloc(ArrayCol * sizeof(int));        // 后列
    memset(Array[i], 0, ArrayCol * sizeof(int));            // 初始化 0
}

for (int i = 0; i < 3; i++)                                    // 释放内存
{
    free(Array[i]);
}
free(Array);                                    
 

 

 

2.用法

2.1一维的用法

1.for循环赋值
    //把指针设置为const类型,防止p后面被改变,这点很重要,之后在下面会特别介绍,防止指针中途改变从而导致最后无法被析构
	int *const p=new int[10];


    //为一维数组赋值
	for(int i=0;i<10;i++){
		p[i]=i+1;
	}

   //调用一维数组
	for(int i=0;i<10;i++){
		cout<<p[i]<<endl;
	}

   //用完记得删除
	delete[]p;

2.初始阶段初始化

int* Array = new int[ArraySize];					// 仅在自由存储区中申请内存,不初始化
int* Array = new int[ArraySize]();					// 初始化数组全为 0
int* Array = new int[5]{ 1,2,3,4,5 };				// 初始化数组为 1,2,3,4,5
int* Array = new int[5]{ 1 };						// 初始化数组为 1,0,0,0,0
delete[] Array;										// 释放内存

2.2二维的用法

C++又规定了数组名代表数组首元素地址,因此array[0]代表一维数组array[0]中第0行第0列元素的地址,即&array[0][0],array[1]的值是&array[1][0],array[2]的值是&array[2][0]。

#include<iostream>//预处理
using namespace std;//命名空间 
int main()//主函数 
{
	//堆区申请内存,创建一个二维数组并为其初始化值。 
	int(*p)[4]=new int[3][4] { {1,2,3,4},{5,6,7,8},{9,10,11,12} };
	int i, j;//定义代表行数和列数的整型变量 
	cout << "输入行号列号:";//提示语句 
	cin >> i >> j;//键盘输入行数和列数 
	cout << *(*(p + i) + j) << endl;//偏移量计算访问法 
	cout << p[i][j] << endl;//不妨称之为几何访问法, 
	return 0; 
}

 

 

 

3.为什么要把指针设置为const?

原回答网址:

https://blog.csdn.net/charlessimonyi/article/details/8277616

常见的通过偏移量来访问的两种方式:

*(pa+2)=15;

pa[2]=15;

下面问题来了:

pa++;

*(pa)=10

这样看上去,对pa指针自加后pa指针指向了数组的第二个元素,然后对第二个元素赋值为10,编译没有错,也能成功赋值。

但要注意!我们在堆中创建的东西用完后需要用delete来释放,对于堆中数组,这样来释放:

delete [] pa;

由于我们刚才对pa进行了自加,这里用delete释放的时候就会出错,因为pa自加后就没有指向数组第一个元素的地址了,系统无法正确的释放我们在堆中创建的数组所占的内存空间。就会出现卡死等异常情况。所以千万不要改变pa指针。

为了防止对pa指针的误操作,最好的办法是将它申明为常指针,我们在一开始堆中创建数组的时候就这样:

int *const pa = new int[10];

将pa申明为常指针后,我们就无法改变pa指针了,比如无法pa++;无法pa+=2;但是我们仍然可以正常的访问和修改pa指向的数组元素的值,pa[1]=10;

delete [] pa;

pa=NULL;

最后,在堆中创建的东西,用完后都要delete以免发生内存泄露。delete释放后指针要及时指向NULL,防止野指针出现。

善用const,可以给我们写程序减少麻烦,尤其是写大型程序的时候。

 

 

 

 

  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
引用的代码展示了使用strcpy_s函数的例子。在这个例子,str1和str2分别是两个字符数组,通过输入字符串并使用strcpy_s函数将str2的内容复制到str1。然后输出str1的值。接下来,引用的代码还使用了动态内存分配来创建一个名为str的字符指针,并使用strcpy_s函数将str1的内容复制到str。 引用的代码展示了在最新的编辑器使用strcpy函数会报错的情况。在这个例子,str1和str2同样是两个字符数组,但是使用的是标准的strcpy函数来进行复制。由于strcpy函数在处理字符串时存在潜在的安全风险,因此在较新的编辑器可能会报出错误。 引用的代码展示了一个简单的使用strcpy_s函数的例子。在这个例子创建了一个名为str的字符指针,并使用strcpy_s函数将一个字符串常量复制到str。 综上所述,strcpy_s函数用于安全地将一个字符串复制到另一个字符串。它是为了解决strcpy函数可能导致的缓冲区溢出问题而设计的。在使用strcpy_s函数时,建议使用编译器提供的最新的安全函数来进行字符串复制操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [C++strcpy()函数和strcpy_s()函数的使用及注意事项](https://blog.csdn.net/leowinbow/article/details/82380252)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ad_m1n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值