动态内存分配技术

前言

当我们的需要自己申请内存空间的大小,而不想通过编译器取申请内存空间时,可以使用内存动态内配技术,这时候申请的内存空间都在堆中,而不是在栈中

一、malloc,calloc,realloc

malloc:C标准库函数

int main() {
	unsigned x;
	std::cin >> x;
	int* p = (int*)malloc(x * sizeof(x));
	if (p == nullptr)
	{
		std::cout << "内存分配失败!";
	}
	else {
		p[0] = 1;
		p[1] = 2;
		p[2] = p[0] * p[1];
		std::cout << p[0] << " " << p[1] << " " << p[2];
	}
	system(0);
	return 0;	
}

calloc:C标准库函数,运行效率低比malloc低

int main() {
	unsigned x;
	std::cin >> x;
	int* p{}, * pm{};
	pm = (int*)malloc(x * sizeof(int));
	p = (int*)calloc(x, sizeof(x));
	std::cout << pm[0] << std::endl;
	std::cout << p[0] << std::endl;
	system(0);
	return 0;
}

realloc():重新分配内存
地址会不会改变取决于重新分配的内存比原来的内存大还是小

int main() {
	unsigned x;
	std::cout << "请输入要分配的内存大小:";
	std::cin >> x;
	int* p{}, * pold;
	p = (int*)calloc(x, sizeof(int));
	pold = p;
	std::cout << p[0] << std::endl;
	if (p == nullptr)
	{
		std::cout << "内存分配失败!";
	}
	else {
		p[0] = 1;
		p[1] = 2;
		p[2] = p[0] * p[1];
		std::cout << p[0] << " " << p[1] << " " << p[2];
	}
	std::cout << "请输入要重新分配的内存大小!";
	std::cin >> x;
	p = (int*)realloc(p, x);
	std::cout << p << "----" << pold << std::endl;
	std::cout << p[0] << " " << p[1] << " " << p[2];
	return 0;
}

二、free

作用:释放内存,一般释放后会将对应的内存指针置空,避免悬空指针的出现

free(p);
p = NULL;

三 new int, new int[]

C++的内存分配运算符,基于C语言的内存分配malloc()实现的new运算符重载函数

    int* pInt = new int;
	int* pInt2 = new int[2];

四 delete, delete[]

C++的内存释放运算符

    int* pInt = new int;
	delete pInt;
	int* pInt2 = new int[2];
	delete[] pInt2;

五 内存分配的风险

1.悬空指针的问题:指针最初指向的内存已经被释放了的一种指针

解决方案1:释放后把对应的指针设置为nullptr,运行起来后编译器会报错!

int main() {
	int* p = nullptr;
	int* p2 = new int;
	p = p2;
	delete p2;
	p = p2 = nullptr;
	*p = 1;
}

解决方案2:使用智能指针

2.野指针问题:没有被初始化过的指针

解决方案1:对于指针初始化时都是赋值为 nullptr ,这样在使用时编译器就会直接报错,产生非法内存访问。

    int* p = nullptr;
	std::cout << *p << std::endl;
	return 0;

解决方案2:养成好的编程习惯,定义指针变量及时初始化

3.重复释放问题:多线程环境下容易造成指针变量的多次释放

解决方案:没有解决方案,只能编码的时候提高警惕性

4.内存碎片问题:待研究(嵌入式开发比较严格,可能会有这样的问题)

六 复制内存

1.for循环

int main() {
	int a[5]{ 1,2,3,4,5 };
	int* b = new int[5];
	for (int i = 0; i < 5; i++)
		b[i] = a[i];
	for (int u = 0; u < 5; u++)
		std::cout << b[u] << std::endl;
}

2.memcpy(…): C语言标准库函数

int main() {
	int a[5]{ 1,2,3,4,5 };
	int* b = new int[5];
	memcpy(b, a, sizeof(a));
	for (int u = 0; u < 5; u++)
		std::cout << b[u] << std::endl;
}

3.memset(…): C语言标准库函数

int main() {
	int a[5]{ 1,2,3,4,5 };
	int* b = new int[5];
	memset(a, 0x1234 /*只能一个字节一个字节的初始化*/ , sizeof(a));
	memcpy(b, a, sizeof(b));
	for (int u = 0; u < 5; u++)
		std::cout << std::hex << a[u] << std::endl;
}

作用:常用于初始化内存空间为0或-1;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值