内置类型空间申请与释放
C++兼容C语言,所以C语言动态申请空间的malloc等函数依旧可以正常使用,但是malloc函数只是申请空间,并不会对空间进行初始化,即使用calloc函数也只能初始化为0,不可以指定值。C++中采用了新的操作符"new"和"delete"来进行动态内存管理可以解决这个问题
int *p = new int(3);//申请一个大小为int的空间,初始化为3
int *p1 = new int[5];//申请5个大小为int的空间
cout << *p << endl;
delete p;//释放单个空间
delete[] p1;//释放一组空间
自定义类型空间申请与释放
C语言中对于自定义类型也同样不可以进行初始化,new在进行申请空间的时候,如果类型为自定义类型的话也会自动调用该类型的构造函数来为新申请的空间初始化。
class Test
{
public:
Test()
: _data(0)
{
cout << "Test():" << this << endl;
}
~Test()
{
cout << "~Test():" << this << endl;
}
private:
int _data;
};
void Test2()
{
// 申请单个Test类型的对象
Test* p1 = new Test;
delete p1;
// 申请10个Test类型的对象
Test* p2 = new Test[10];
delete[] p2;
}
new在申请空间时调用构造函数,delete函数在进行空间释放时会调用析构函数来清理对象的资源。
operator new与operator delete函数
事实上new在进行申请空间时,是调用了operator new函数(这不是函数重载,而是函数名本就如此)来进行申请空间,而从下面的函数代码中也可以看到,operator new函数内部其实也是用malloc申请空间的,不同的是函数内加了判断,若申请空间失败则会跑出异常,而不是和malloc函数一样返回0,在这里申请空间成功后,在根据初始值或调用构造函数对空间进行初始化。
delete最终也是调用operator delete函数来进行释放空间,最终与free函数一样也是通过_free_dbg函数进行释放空间。
/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,
尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否则抛异常。
*/
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 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);
__FINALLY
_munlock(_HEAP_LOCK); /* release other threads */
__END_TRY_FINALLY
return;
}
/*
free的实现
*/
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
定位new表达式(placement-new)
定位new是为了对一块未初始化的空间进行初始化的。
使用格式:
new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
class Test
{
public:
Test()
: _data(0)
{
cout << "Test():" << this << endl;
}
~Test()
{
cout << "~Test():" << this << endl;
}
private:
int _data;
};
void Test()
{
// pt现在指向的只不过是与Test对象相同大小的一段空间,还不能算是一个对象,因为构造函数没有执行
Test* pt = (Test*)malloc(sizeof(Test));
new(pt) Test; // 注意:如果Test类的构造函数有参数时,此处需要传参
}