您的位置:首页 > 编程语言 > C语言/C++

C++ new 用法

2016-04-01 17:49 134 查看
先看一下new和malloc的区别:

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

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

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

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

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

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

1.new 的三种使用方式

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

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

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

动态创建对象数组举例

[cpp] view
plain copy

#include<iostream>

using namespace std;

class Point

{

public:

Point()

{ X=Y=0; cout<<"Default Constructor called.\n";}

Point(int xx,int yy)

{ X=xx; Y=yy; cout<< "Constructor called.\n"; }

~Point() { cout<<"Destructor called.\n"; }

int GetX() {return X;}

int GetY() {return Y;}

void Move(int x,int y){ X=x; Y=y; }

private:

int X,Y;

};

void main()

{

Point *Ptr=new Point[2]; //创建对象数组

Ptr[0].Move(5,10); //通过指针访问数组元素的成员

Ptr[1].Move(15,20); //通过指针访问数组元素的成员

cout<<"Deleting..."<<endl;

delete[ ] Ptr; //删除整个对象数组

}

动态数组类

[cpp] view
plain copy

#include<iostream>

using namespace std;

class Point

{

public:

Point()

{ X=Y=0; cout<<"Default Constructor called.\n";}

Point(int xx,int yy)

{ X=xx; Y=yy; cout<< "Constructor called.\n"; }

~Point() { cout<<"Destructor called.\n"; }

int GetX() {return X;}

int GetY() {return Y;}

void Move(int x,int y){ X=x; Y=y; }

private:

int X,Y;

};

class ArrayOfPoints //这个类叫“控制类”

{

public:

ArrayOfPoints(int n) // 按照指示创建指定个数的对象

{

numberOfPoints = n;

points = new Point
;

}

~ArrayOfPoints()

{

cout<<"Deleting..."<<endl;

numberOfPoints=0;

delete[] points;

}

Point& Element(int n)

{

return points
;

}

private:

Point *points; //类内只保存对象数组的首址

int numberOfPoints; //对象的个数

};

void main()

{

int number;

cout<<"Please enter the number of points:";

cin>>number; //由用户指定对象个数

//创建ArrayOfPoints对象points,该对象聚集了//Point类的对象数组

ArrayOfPoints points(number);

//通过指针访问数组元素的成员(两个层次)

points.Element(0).Move(5,10);

cout<<"points.Element(0): "<<points.Element(0).GetX()<<","<<points.Element(0).GetY()<<endl;

//通过指针访问数组元素的成员

points.Element(1).Move(15,20);

cout<<"points.Element(1): "<<points.Element(1).GetX()<<","<<points.Element(1).GetY()<<endl;

}

输出结果:

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; //再释放内存.

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