1. C/C++内存管理
int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
static int staticVar = 1;
int localVar = 1;
int num1[10] = { 1, 2, 3, 4 };
char char2[] = "abcd";
const char* pChar3 = "abcd";
int* ptr1 = (int*)malloc(sizeof(int) * 4);
int* ptr2 = (int*)calloc(4, sizeof(int));
int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
free(ptr1);
free(ptr3);
}
2.sizeof()在编译时计算好了,strlen()在运行时计算
3.sizeof()计算出对象使用的最大字节数,strlen()计算字符串的实际长度(不包含‘/0’)
4.sizeof()的参数类型多样化(数组,指针,对象,函数都可以),strlen()的参数必须是字符型指针
![](https://img-blog.csdnimg.cn/6ab29ee5aeb140dd9f0b98f9ab4cb709.png)
[问题]malloc/calloc/realloc的区别
calloc-分配内存、把内存清零。
malloc-分配内存、不把内存清零。
realloc-重新分配内存,把之前的数据搬到新内存去。
realloc(NULL, size)等价于malloc(size)。
calloc(num, size)基本上等于void *p = malloc(num *size); memset(p, 0, num * size);但理论上calloc的实现可避免 num * size溢出,当溢出时返回NULL代表失败,而malloc(num * size)可能会分配了一个尺寸溢出后的内存。
2. new/delete使用方法
1.内置类型
#include <iostream>
using namespace std;
int main()
{
int* p1 = new int;//在堆区申请一个int大小的空间,并未初始化
int* p2 = new int(1);//在堆区申请一个int大小的空间,并初始化为0
delete p1;//释放p1所指向的空间
delete p2;
int* p3 = new int[10];//在堆区申请一个10*int大小的空间,并未初始化
int* p4 = new int[10]{1,2,3};//在堆区申请一个10*int大小的空间,并初始化为{1,2,3,0,0,0,0,0,0,0}
delete[] p3;//释放p3所指向的空间,注意申请多个空间要加[]
delete[] p4;
}
2.自定义类型
class Date
{
public:
// 默认构造函数
Date(int year = 1, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
{}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year;
int _month;
int _day;
};
int main()
{
// 开辟一个自定义类型的一个日期类大小的空间
// 调用无参/全缺省构造函数
Date* ptr1 = new Date;
// 调用有参构造函数
Date* ptr2 = new Date(2023, 8, 19);
// 开辟一个自定义类型(日期类)的连续空间
// 自动调用-默认构造函数-完成日期类的初始化操作
// 如果没有默认构造函数,编译器报错
Date* ptr3 = new Date[3];
ptr1->Print();//调用Date类函数
ptr2->Print();
ptr3->Print();
// 释放自定义类型的空间
// 1.先调用析构函数清理资源
// 2.再释放空间
delete ptr1; // 调用一次析构函数,再释放空间
delete ptr2; // 调用一次析构函数,再释放空间
delete[] ptr3; // 调用三次析构函数,再释放空间(仅一次)
return 0;
// 注意:在申请自定义类型的空间时
// new会调用构造函数,delete会调用析构函数
// 而malloc与free不会
}
3. new、delete和malloc、free的区别
1、对于内置类型,没有区别。
2、new和delete是C++的关键字/操作符,而malloc和free是C语言的库函数。
3、对于自定义类型,相比于malloc和free,new和delete会额外调用类中的构造函数和析构函数。
4、malloc的返回值是void*,使用时需要强转,new后边跟的是空间的类型,所以new不需要强转。
5、malloc失败返回空指针,需要判空;new失败抛异常,需要捕获异常。
4.new/delete的原理
1.new原理
new等于operator new()+构造函数。operator new()不是new运算符的重载,因为参数没有自定义类型。它是一个库里的全局函数。
void *__CRTDECL operator new(size_t size) _THROW1(_STD bad_alloc)
{
// try to allocate size bytes
void *p;
while ((p = malloc(size)) == 0)
if (_callnewh(size) == 0)
{
// report no memory
// 如果申请内存失败了,这里会抛出bad_alloc 类型异常
static const std::bad_alloc nomem;
_RAISE(nomem);
}
return (p);
}
从底层代码可以看出operator new()是对malloc的封装,如果malloc失败,将会抛出异常。
2.delete原理
delete等于operator delete()+析构函数
//operator delete: 该函数最终是通过free来释放空间的
void operator delete(void *pUserData) {
_CrtMemBlockHeader * pHead;
RTCCALLBACK(_RTC_Free_hook, (pUserData, 0));
if (pUserData == NULL)
return;
_mlock(_HEAP_LOCK); /* block other threads */
__TRY
/* get a pointer to memory block header */
pHead = pHdr(pUserData);
/* verify block type */
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
_free_dbg( pUserData, pHead->nBlockUse );//调用free()
__FINALLY
_munlock(_HEAP_LOCK); /* release other threads */
__END_TRY_FINALLY
return; }
//free的实现
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
.从底层代码可以看出operator delete()调用了free。
所以针对内置类型或无资源的类对象delete时,使用delete和free效果相同。但对于有资源需要释放的对象时,直接使用free虽然释放了对象的空间,但对象内部的资源还未被清理,导致内存泄漏!这种情况必须使用delete。