C++ new 用法

来源:互联网 发布:软件合作开发合同范本 编辑:程序博客网 时间:2024/05/01 23:55

先看一下new和malloc的区别:

动态存储分配的运算符与函数的区别

malloc( )和free()是动态存储管理函数;

new 和delete是动态存储管理运算符。

它们功能类似但完全不同。

前者是函数,运行需要头文件,返回值无类型,创建对象时不调用构造函数(销毁对象时不调用析构函数);

而后者是运算符,不需要头文件,返回值有类型,创建对象时调用构造函数(销毁对象时调用析构函数)。


1.new 的三种使用方式

指针= new 类型名T                     此时将调用无参构造函数;

指针= new 类型名T(初值列表)  此时将调用有参构造函数;

指针= new 类型名T [ size ]           此时将调用无参构造函数;


动态创建对象数组举例

[cpp] view plain copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class Point  
  4. {   
  5. public:  
  6.     Point()  
  7.     { X=Y=0; cout<<"Default Constructor called.\n";}  
  8.     Point(int xx,int yy)  
  9.     { X=xx; Y=yy; cout<< "Constructor called.\n"; }  
  10.     ~Point() { cout<<"Destructor called.\n"; }  
  11.     int GetX() {return X;}  
  12.     int GetY() {return Y;}  
  13.     void Move(int x,int y){ X=x; Y=y; }  
  14. private:  
  15.     int X,Y;  
  16. };  
  17.   
  18.   
  19. void main()  
  20. {   
  21.     Point *Ptr=new Point[2]; //创建对象数组  
  22.     Ptr[0].Move(5,10); //通过指针访问数组元素的成员  
  23.     Ptr[1].Move(15,20); //通过指针访问数组元素的成员  
  24.     cout<<"Deleting..."<<endl;  
  25.     delete[ ] Ptr; //删除整个对象数组  
  26. }  

动态数组类

[cpp] view plain copy
  1. #include<iostream>  
  2. using namespace std;  
  3. class Point  
  4. {   
  5. public:  
  6.     Point()  
  7.     { X=Y=0; cout<<"Default Constructor called.\n";}  
  8.     Point(int xx,int yy)  
  9.     { X=xx; Y=yy; cout<< "Constructor called.\n"; }  
  10.     ~Point() { cout<<"Destructor called.\n"; }  
  11.     int GetX() {return X;}  
  12.     int GetY() {return Y;}  
  13.     void Move(int x,int y){ X=x; Y=y; }  
  14. private:  
  15.     int X,Y;  
  16. };  
  17.   
  18.   
  19. class ArrayOfPoints     //这个类叫“控制类”  
  20. {   
  21. public:  
  22.     ArrayOfPoints(int n) // 按照指示创建指定个数的对象  
  23.     {   
  24.         numberOfPoints = n;  
  25.         points = new Point[n];   
  26.     }  
  27.     ~ArrayOfPoints()  
  28.     {   
  29.         cout<<"Deleting..."<<endl;  
  30.         numberOfPoints=0;   
  31.         delete[] points;   
  32.     }  
  33.     Point& Element(int n)  
  34.     {   
  35.         return points[n];   
  36.     }  
  37. private:  
  38.     Point *points; //类内只保存对象数组的首址  
  39.     int numberOfPoints; //对象的个数  
  40. };  
  41.   
  42.   
  43. void main()  
  44. {  
  45.     int number;  
  46.     cout<<"Please enter the number of points:";  
  47.     cin>>number; //由用户指定对象个数  
  48.     //创建ArrayOfPoints对象points,该对象聚集了//Point类的对象数组  
  49.     ArrayOfPoints points(number);  
  50.     //通过指针访问数组元素的成员(两个层次)  
  51.     points.Element(0).Move(5,10);  
  52.     cout<<"points.Element(0): "<<points.Element(0).GetX()<<","<<points.Element(0).GetY()<<endl;  
  53.     //通过指针访问数组元素的成员  
  54.     points.Element(1).Move(15,20);  
  55.     cout<<"points.Element(1): "<<points.Element(1).GetX()<<","<<points.Element(1).GetY()<<endl;  
  56. }  

输出结果:

Please enter the number of points:2
Default Constructor called.
Default Constructor called.
points.Element(0): 5,10
points.Element(1): 15,20
Deleting...
Destructor called.
Destructor called.
Press any key to continue


动态创建多维数组
指针= new 类型名T[下标表达式1][下标表达式2]…;

如果内存申请成功,new运算返回一个指向新分配内存首地址的指针,是一个T类型的数组。

数组元素的个数为除最左边一维外各维下标表达式的乘积。

例如:char (*fp)[3];   fp= new char[2][3];

fp应是个指向多维数组的指针,指针的类型应是char [3],这是“大元素”类型,其中内嵌了一维数组。所以*fp一定要加括号,所以一定比对象数组少一维。


创建动态对象数组的又几种形式
Point a[2]={Point(1,2),Point(3,4)};
这叫“创建对象数组”,尽管无名,但不在堆区,在栈区。
Point b[2]={*new Point(1,2),*new Point(3,4)};
这叫“动态创建对象数组”,在堆区。
Point *Ptr=new Point[2]; 
这叫“动态创建无名对象数组”,在堆区。
Point *c[2]={new Point(1,2), new Point(3,4)};
这叫“动态创建对象指针数组”,在堆区。


new 的种类
plain new 普通new
void*operator new(std::size_t)throw(std::bad_alloc);
void operator delete( void *) throw();
nothrownew 不抛掷异常new
void*operator new(std::size_t,conststd::nothrow_t
& )throw();
void operator delete( void *) throw();
placement new 放置new
void*operator new(std::size_t,void );
void operator delete( void * ,void );

1. 普通new 的用法
该运算符在分配失败时将抛出异常,而非返回NULL。使用时要包含<new>头文件。
char *getMemory(unsignedlong size)

char * p = newchar[size];
return p;

 }
void main(void)
{

try{
char * p = getMemory(1000000);//可能发生异常
// ...
delete [ ] p;
}
catch(conststd::bad_alloc& ex)
{ cout<<ex.what(); }

}

2.不抛掷异常new 的用法
该运算符在分配失败时不抛出异常,而是返回NULL。使用时要包含<new>头文件。
该函数的第2形参是structnothrow_t{ };类的全局常对象const nothrow_tnothrow; 用来作为new 运算符的标志.
void func(unsingedlong length)
{ unsingedchar * p = new(nothrow)
unsingedchar[length];
if ( p == NULL)
cout<<“alloctefailed !”;
// ...
delete [ ] p;
}


3.放置new 的用法
该运算符是在已分配的内存上重新构造对象,因为不分配内存,所以不必担心分配失败。唯一的工作是调用构造函数。要包含<new>头文件。

# include <new>

# include<iostream>

void main()

using namespace std;

char * p = new(nothrow) char [4]; //用nothrow

if (p == NULL)

{ cout<<“alloctefailed”<<endl; exit( -1 ); }

long * q = new(p)long(1000); //用placement

delete [ ]p; //只释放p,不要释放q.

}

p和q仅仅是首址相同,所构建的对象可以类型不同。所“放置”的空间应小于原空间,以防不测。

该运算符的作用是:只要第一次分配成功,不再担心分配失败。
# include <new>
# include<iostream>
void main()
{ using namespace std;
char * p = new(nothrow) char [100]; //用nothrow
if (p == NULL)
{ cout<<“alloctefailed”<<endl; exit( -1 ); }
// ...
long * q1 = new(p)long(100); //用placement
// ...
long * q2 = new(p) int[100/sizeof(int) ];
// ...
ADT * q3 = new(p) C[100/sizeof(ADT) ];
delete [ ]p; //释放.
}


注意:使用该运算符一定要显式调用析构函数,不可用delete代替析构,因为placement new 的对象的大小不再与原空间相同。
# include <new>
# include<iostream>
void main()
{ using namespace std;
char * p = new(nothrow) char [sizeof(ADT)+2];
if (p == NULL)
{ cout<<“alloctefailed”<<endl; exit( -1 ); }
// ...
ADT * q = new(p) ADT;
// ...
// delete q; // 错误
q-> ADT::~ADT();
delete [ ]p; //再释放内存.
}


0 0
原创粉丝点击