IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 动态内存分配 -> 正文阅读

[C++知识库]动态内存分配

动态内存分配

函数名描述
malloc()保留一个被请求的字节数和返回一个指向第一个被保留的字节的指针。eg:malloc(50 * sizeof(int))保留足够字节数存储50个整数,malloc()返回一个指向被保留存储区第一个字节的指针。因为被返回的指针总是“指向”一个void,所以它中总是被强制转换成一个期望类型指针。
calloc()为一个被指定大小的n个元素的数组保留空间。返回第一个保留位置的地址并初始化所有保留的字节为0。或者返回NULL
realloc()改变前面分配存储区的数量(收缩/扩张)
free()释放前面保留的字节块。第一个保留位置的地址作为参数传递给free()函数
// An highlighted block
int *intPtr;
intPtr = (int*) malloc(50 * sizeof(int));

malloc()为数组请求空间

/*
1、用malloc分配空间,把首地址给grades
2、判断分配是否成功
3、把grades的内存用free归还
*/
#include <stdio.h>
#include <stdlib.h>

int main()
{
	int numgrades, i;
	int *grades;

	printf("\n输入个数 : ");
	scanf_s("%d", &numgrades);
	grades = (int*)malloc(numgrades * sizeof(int));

	//检查分配是否被满足,把NULL强制转换成一个指向转换整数的指针
	if (grades ==(int*) NULL)
	{
		printf("\nfailed");
		exit(1);
	}

	for (i = 0; i < numgrades; i++)
	{
		printf("输入数值:");
		scanf_s("%d", &grades[i]);
	}

	for ( i = 0; i < numgrades; i++)
		printf("%d\n",grades[i]);

	//把堆的内存归还给计算机
	free(grades);
	system("pause");
	return 0;
}
var foo = 'bar';

输出:
在这里插入图片描述

malloc()为结构体动态分配存储空间

// An highlighted block
typedef struct Rectangle
{
    uint64_t area_sign;
    int left;
    int top;
    int right;
    int bottom;
}Rectangle;

typedef struct rectangleSet
{
    int area_count;
    Rectangle area[0];
}rectangleSet;

#define MAX_AREA_COUNT 128
//创建指针将存储分配的地址
rectangleSet *area;
//为结构体请求空间,并且强制转换这个返回的地址为一个正确的结构类型指针
area = (rectangleSet*)malloc(sizeof(rectangleSet)+sizeof(Rectangle)*MAX_AREA_COUNT);
if(area == (rectangleSet*)NULL)
{
	printf("\nfailed");
	exit(1);
}
memset(area ,0, sizeof(rectangleSet)+sizeof(Rectangle)*MAX_AREA_COUNT);

malloc()和new的区别

(1)为对象申请内存位置

项目内存位置内存位置解释
new操作符自由存储区(free store)自由存储区是C++基于new操作符的一个抽象概念,凡是通过new操作符进行内存申请,该内存即为自由存储区。自由存储区可以是堆,也可以是静态存储区。
malloc函数堆 (heap)堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于程序的内存动态分配,C语言使用malloc从堆上分配内存,使用free释放已分配的对应内存。

(2)返回类型安全性

项目返回类型安全性
new操作符内存分配成功时,返回的是对象类型的指针,类型严格与对象匹配,无须进行类型转换符合类型安全性
malloc函数内存分配成功时,返回void * ,需要通过强制类型转换将void*指针强转成需要的类型不符合类型安全性

(3)内存分配失败时的返回值

new内存分配失败时,会抛出bac_alloc异常,它不会返回NULL;malloc分配内存失败时返回NULL。
在使用C语言时,我们习惯在malloc分配内存后判断分配是否成功:

 int *a  = (int *) malloc (sizeof(int ));
 if(a ==(int*) NULL)
{
    ...
}
 else
{
    ...
} 

C++

 int * a = new int();
if(a== NULL)
{
    ...
}
else
{   
    ...
} 

new根本不会返回NULL,而且程序能够执行到if语句已经说明内存分配成功了,如果失败早就抛异常了。正确的做法应该是使用异常机制:

try
{
    int *a = new int();
}
catch (bad_alloc)
{
    ...
}

(4)是否需要指定内存大小

使用new操作符申请内存分配时无须指定内存块的大小,编译器会根据类型信息自行计算,而malloc则需要显式地指出所需内存的尺寸。

class A{…}
A * ptr = new A;
A * ptr = (A *)malloc(sizeof(A)); //需要显式指定所需内存大小sizeof(A);

(5)是否调用构造函数/析构函数

使用new操作符来分配对象内存时:

第一步:调用operator new 函数(对于数组是operator new[])分配一块足够大的,原始的,未命名的内存空间以便存储特定类型的对象。
第二步:编译器运行相应的构造函数以构造对象,并为其传入初值。
第三部:对象构造完成后,返回一个指向该对象的指针。
使用delete操作符来释放对象内存时会经历两个步骤:

使用delete操作符来释放对象内存时:

第一步:调用对象的析构函数。
第二步:编译器调用operator delete(或operator delete[])函数释放内存空间。
总之来说,new/delete会调用对象的构造函数/析构函数以完成对象的构造/析构。而malloc则不会。
例如:

#include <stdio.h>
#include <stdlib.h>
class A
{
public:
	A() :a(1), b(1.11) {}
private:
	int a;
	double b;
};
int main()
{
	A * ptr = (A*)malloc(sizeof(A));
	A *aPtr = new A();
	return 0;
}

设置断点
在这里插入图片描述malloc动态分配内存并没有调用A的默认构造函数,而new操作符分配空间调用默认构造函数初始化指针,所以使用malloc/free来分配C++的自定义类型内存不合适,其实不止自定义类型,标准库中凡是需要构造/析构的类型通通不合适。

(6)对数组的处理

C++提供了new[]与delete[]来专门处理数组类型:

A * ptr = new A[10];//分配10个A对象
使用new[]分配的内存必须使用delete[]进行释放:

delete [] ptr;
new对数组的支持体现在它会分别调用构造函数函数初始化每一个数组元素,释放对象时为每个对象调用析构函数。注意delete[]要与new[]配套使用,不然会找出数组对象部分释放的现象,造成内存泄漏。

malloc()/free()函数分配释放数组内存
int * ptr = (int *) malloc( 10 * sizeof(int) );//分配一个10个int元素的数组
free(ptr);

此外;

int *intPtr = new int();
delete intPtr;

执行完该语句后,intPtr变成了不确定的指针,在很多机器上,尽管intPtr值没有明确定义,但仍然存放了它之前所指对象的地址,然后intPtr所指向的内存已经被释放了,所以intPtr不再有效。此时,该指针变成了悬垂指针(悬垂指针指向曾经存放对象的内存,但该对象已经不存在了)。悬垂指针往往导致程序错误,而且很难检测出来。
因此释放指针之后要给他们重新赋空值

int *intPtr = new int();
delete intPtr;
intPtr = NULL;

链接: link.

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 17:22:53  更:2022-04-18 17:25:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:51:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码