C++ new 用法

本文详细介绍了C++中new和malloc的区别,new的不同使用方式及其应用场景,包括动态创建对象数组、多维数组及对象指针数组等。同时,还探讨了不同类型new(如普通new、不抛掷异常new和放置new)的使用方法。
摘要由CSDN通过智能技术生成

先看一下new和malloc的区别:

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

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

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

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

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

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


1.new 的三种使用方式

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

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

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


动态创建对象数组举例

#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; //删除整个对象数组
}

动态数组类

#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[n]; 
	}
	~ArrayOfPoints()
	{ 
		cout<<"Deleting..."<<endl;
		numberOfPoints=0; 
		delete[] points; 
	}
	Point& Element(int n)
	{ 
		return points[n]; 
	}
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; //再释放内存.
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值