您的位置:首页 > 其它

对 malloc free ,new,delete 的思考与探索——1

2015-07-25 11:22 363 查看
首先说一下new的三种形式:

new有三种使用方式:plain new,nothrow new和placement new。

(1)plain new顾名思义就是普通的new,就是我们惯常使用的new。在C++中是这样定义的:

void* operator new(std::size_t) throw(std::bad_alloc);

void operator delete(void *) throw();

提示:plain new在分配失败的情况下,抛出异常std::bad_alloc而不是返回NULL,因此通过判断返回值是否为NULL是徒劳的。

(2)nothrow new是不抛出异常的运算符new的形式。nothrow new在失败时,返回NULL。定义如下:

void * operator new(std::size_t,const std::nothrow_t&) throw();

void operator delete(void*) throw();

(3)placement new意即“放置”,这种new允许在一块已经分配成功的内存上重新构造对象或对象数组。placement new不用担心内存分配失败,因为它根本不分配内存,它做的唯一一件事情就是调用对象的构造函数。定义如下:(有时候也可以叫定位new)

void* operator new(size_t,void*);

void operator delete(void*,void*);

提示1:palcement new的主要用途就是反复使用一块较大的动态分配的内存来构造不同类型的对象或者他们的数组。

提示2:使用placement new构造起来的对象或数组,要显式调用它们的析构函数来销毁(析构函数并不释放对象的内存),千万不要使用delete.这是因为placement new构造起来的对象或数组大小并不一定等于原来分配的内存大小,使用delete会造成内存泄漏或者之后释放内存时出现运行时错误。

char* p = new(nothrow) char[100];

long *q1 = new(p) long(100);

int *q2 = new(p) int[100/sizeof(int)]

/**********************************************************************
* *   Copyright (c)2015,WK Studios
* *   Filename:  A.h
* *   Compiler: GCC  vc 6.0
* *   Author:WK
* *   Time: 2015 25 7
* *********************************************************************
#include<iostream>
using namespace std;

/*
//malloc 和free函数,new之中内置了sizeof 类型转换,和类型安全检查对于非内部类型对象来说动态创建对象的同时完成了初始化
void* malloc(size_t size)//这里是字节的个数
{

}
void free(void *memblock)//指针的类型和所指内存中的容量事先已经知道,对于NULL指针可以释放无数次,对于非NULL的指针只能释放一次
{                         //free()并没有将指针的内容释放变为随机值,而是将指针中存储的地址所对应的那块内存释放变为随机值,所以此时不能访问那块内存中的数据,但是你可以通过指针找到那块内存,只是读取其中的内容是非法的

}
//plain new/delete,标准C/C++中申请失败时候会抛出标准异常,所以必须在使用的时候设置异常处理器
void* operator new(size_t lenth)throw(std::bad_alloc)
{

}
void operator delete(void* memblock)throw()
{

}

//nothrow new/delete,申请失败的时候返回NULL,使用的时候不需要设置异常处理器
void* operator new(size_t lenth,const std::nothrow_t &ex)throw()
{

}

void operator delete(void* memblock)throw();

//placement new/delete
void* _operator new(size_t void* mem)
{

}

void _operator delete(void* mem,void* bloc)
{

}
*/

//nothrow new/delete使用
void func(size_t lenth)
{
unsigned char *p = new(nothrow) unsigned char[lenth];
if(p == NULL)
{
cout<<"allocate failed!!\n";
exit(-1);
}
delete []p;
}

//plain new/delete使用
char * GetMemory(unsigned long   lenth)
{
char *p = new char[lenth];
return p;
}

class base
{
public:
base(int a=0):m_a(a)
{

}
~base()
{

}
private:
int m_a;
};

void main()
{

//malloc free的使用
long *buffer;
long *buffer1;
buffer1=(long *)malloc(40*sizeof( long ) );//空间随机值
if( buffer1 != NULL )
printf( "Allocated 40 long integers\n" );
else
printf( "Can't allocate memory\n" );

buffer = (long *)calloc( 40, sizeof( long ) );//空间全部置0
if( buffer != NULL )
printf( "Allocated 40 long integers\n" );
else
printf( "Can't allocate memory\n" );
free( buffer );
free( buffer1 );
try
{
char *p = GetMemory(100000000);
delete []p;
}
catch(const std::bad_alloc& ex)
{
cout<<ex.what()<<endl;

}
catch(...)
{
cout<<"ERROR!!!\n";
}

func(100);
//placement new  允许在已经成功分配的内存上边重新构造对象或者对象数组,根本不用担心内存分配失败,因为定位New并没有分配内存只是调用了构造函数创建对象
char*p = new(nothrow)char[sizeof(base)];//nothrow new
if(p == NULL)
{
cout<<"allocate failed!!\n";
exit(-1);
}

base *q = new(p) base(1000);//placement new
q->~base();//要显示的调用析构函数
delete []p;

char *pb = new(nothrow) char[sizeof(int)*10];
if(pb == NULL)
{
cout<<"allocate failed!!\n";
exit(-1);
}
int *qb = new(pb) int(10);
delete []pb;

//多次delete或者free一个NULL指针没有危险,因为delete会首先检查这种情况,指针为NULL,直接返回,但是非NULL的指针只能delete或者free一次

int *pa = NULL;
free(p);
free(p);
delete(p);
delete(p);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: