c++中new的用法

时间:2023-01-29 14:33:28

new是C++中用于动态内存分配的运算符,在C语言中一般使用malloc函数

 

(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是徒劳的。

#include "stdafx.h"
#include <iostream>
using namespace std;

char *GetMemory(unsigned long size)
{
char *p=new char[size];//分配失败,不是返回NULL
return p;
}

int main()
{
try
{
  char *p=GetMemory(10e11);// 分配失败抛出异常std::bad_alloc
  //...........
  if(!p)//徒劳
   cout<<"failure"<<endl;
  delete [] p;

}
catch(const std::bad_alloc &ex)
{
  cout<<ex.what()<<endl;
}

    return 0;
}

 

 

(2)nothrow new是不抛出异常的运算符new的形式。nothrow new在失败时,返回NULL。定义如下:
    void * operator new(std::size_t,const std::nothrow_t&) throw();
    void operator delete(void*) throw();

  

#include "stdafx.h"
#include <iostream>
#include <new>
using namespace std;

char *GetMemory(unsigned long size)
{
char *p=new(nothrow) char[size];//分配失败,是返回NULL
if(NULL==p)
  cout<<"alloc failure!"<<endl;
return p;
}

int main()
{
try
{
  char *p=GetMemory(10e11);
  //...........
  if(p==NULL)
   cout<<"failure"<<endl;
  delete [] p;

}
catch(const std::bad_alloc &ex)
{
  cout<<ex.what()<<endl;
}

    return 0;
}

 

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

palcement new的主要用途就是反复使用一块较大的动态分配的内存来构造不同类型的对象或者他们的数组。placement new构造起来的对象或其数组,要显示的调用他们的析构函数来销毁,千万不要使用delete。

#include "stdafx.h"
#include <iostream>
#include <new>
using namespace std;

class ADT
{
int i;
int j;
public:
ADT()
{
}
~ADT()
{
}
};

int main()
{
char *p=new(nothrow) char[sizeof(ADT)+2];
if(p==NULL)
  cout<<"failure"<<endl;

ADT *q=new(p) ADT;  //placement new:不必担心失败
// delete q;//错误!不能在此处调用delete q;
q->ADT::~ADT();//显示调用析构函数
delete []p;
    return 0;
}

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

另:

当使用new运算符定义一个多维数组变量或数组对象时,它产生一个指向数组第一个元素的指针,返回的类型保持了除最左边维数外的所有维数。例如:  

 int *p1 = new int[10];   

返回的是一个指向int的指针int*  

int (*p2)[10] = new int[2][10]; 

new了一个二维数组, 去掉最左边那一维[2], 剩下int[10], 所以返回的是一个指向int[10]这种一维数组的指针int (*)[10].  

int (*p3)[2][10] = new int[5][2][10];  new了一个三维数组, 去掉最左边那一维[5], 还有int[2][10], 所以返回的是一个指向二维数组int[2][10]这种类型的指针int (*)[2][10].     

#include<iostream>

#include <typeinfo> 

using namespace std;

 int main() { 

int *a = new int[34]; 

int *b = new int[]; 

int (*c)[2] = new 

int[34][2]; 

int (*d)[2] = new int[][2]; 

int (*e)[2][3] = new int[34][2][3];

 int (*f)[2][3] = new int[][2][3];

 a[0] = 1; 

 b[0] = 1; //运行时错误,无分配的内存,b只起指针的作用,用来指向相应的数据

 c[0][0] = 1;

d[0][0] = 1;//运行时错误,无分配的内存,d只起指针的作用,用来指向相应的数据 

e[0][0][0] = 1; 

f[0][0][0] = 1;//运行时错误,无分配的内存,f只起指针的作用,用来指向相应的数据 

cout<<typeid(a).name()<<endl;

 cout<<typeid(b).name()<<endl;

 cout<<typeid(c).name()<<endl; 

cout<<typeid(d).name()<<endl; 

cout<<typeid(e).name()<<endl;

 cout<<typeid(f).name()<<endl; 

delete[] a; delete[] b; delete[] c; 

delete[] d; delete[] e; delete[] f; 

}   

输出结果:

 int *

int *

int (*)[2]

int (*)[2]

int (*)[2][3]

int (*)[2][3]