C++中new的三种使用方法说明

融资困难
• 阅读 5369

一、概念

在C++中new的三种用法包括:plain new, nothrow new 和 placement new。

plain new 就是我们最常使用的new的方式,在C++中的定义如下:

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

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

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

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

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

1 void* operator new(size_t, void*);
2 void operator delete(void*, void*);

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

二、示例

plain new

char *getMemory(unsigned long size)   
{    
    char * p = new char[size];   
    return p; 
}   
void main(void)   
{
    try{   
        char * p = getMemory(1000000);    // 可能发生异常
        // ...   
        delete [] p;   
    }   
    catch(const std::bad_alloc & ex)   
    {
        cout << ex.what();
    }   
}

nowthrow new

void func(unsinged long length)   
{
    unsinged char * p = new(nothrow) unsinged char[length];   
    // 在使用这种new时要加(nothrow) ,明示不使用异常处理 。
 
    if (p == NULL)  // 因不抛异常,故定要检查
        cout << "allocte failed !";   
        // ...   
    delete [] p;
}

placement new

void main()   
{  
    using namespace std;   
    char * p = new(nothrow) char [4];   
    if (p == NULL)   
    {
        cout << "allocte failed" << endl;  
        exit( -1 );
    }   
    // ...   
    long * q = new (p) long(1000);   
    delete []p;    // 只释放 p,不要用q释放。
}

p和q仅仅是首址相同,所构建的对象可以类型不同。所“放置”的空间应小于原空间,以防不测。当”放置new”超过了申请的范围,Debug版下会挂机,但Release版竟然能运行而不出错!
该运算符的作用是:只要第一次分配成功,不再担心分配失败。

void main()   
{
    using namespace std;   
    char * p = new(nothrow) char [100];   
    if (p == NULL)   
    {  
        cout << "allocte failed" << endl;
        exit(-1);
    }   
    long * q1 = new (p) long(100);   
    // 使用q1  ...   
    int * q2 = new (p) int[100/sizeof(int)];   
    // 使用q2 ...   
    ADT * q3 = new (p) ADT[100/sizeof(ADT)];   
    // 使用q3  然后释放对象 ...   
    delete [] p;    // 只释放空间,不再析构对象。
}

注意:使用该运算符构造的对象或数组,一定要显式调用析构函数,不可用delete代替析构,因为placement new 的对象的大小不再与原空间相同。

void main()   
{  
    using namespace std;   
    char * p = new(nothrow) char [sizeof(ADT)+2];   
    if (p == NULL)   
    {  
        cout << "allocte failed" &lt;&lt; endl;
        exit(-1); 
    } 
    // ... 
    ADT * q = new (p) ADT; 
    // ... 
    // delete q; // 错误
    q->ADT::~ADT();  // 显式调用析构函数,仅释放对象
    delete [] p;     // 最后,再用原指针来释放内存
}

placement new 的主要用途就是可以反复使用一块已申请成功的内存空间。这样可以避免申请失败的徒劳,又可以避免使用后的释放。
特别要注意的是对于 placement new 绝不可以调用的delete, 因为该new只是使用别人替它申请的地方(只是个租房户,不是房主。无权将房子卖掉)。释放内存是nothrow new的事,即要使用原来的指针释放内存。

C++中new的三种使用方法说明

点赞
收藏
评论区
推荐文章
半臻 半臻
4年前
Python基础7——单例模式
15单例模式15.1init和new方法执行步骤1.实例化一个对象,先执行new方法,在new方法中返回对象2.然后再调用init方法15.1.1\\init\\方法init是构造方法<fontcolor"red"其实最先调用的方法是new方法</font,但是大部分情况下是不使用new方法pythonclassTest(object):
Easter79 Easter79
3年前
String 和 new String()的区别
String和newString()的区别ForExampleStringstr1"ABC"Stringstr2newString("ABC");Stringstr1"ABC";可能创建一个对象或者不创建对象。如果"ABC"这个字符串z在javaString池中不存在,会在javaString池中
Stella981 Stella981
3年前
JavaScript中的“ new”关键字是什么?
问题:_ThenewkeywordinJavaScriptcanbequiteconfusingwhenitisfirstencountered,aspeopletendtothinkthatJavaScriptisnotanobjectorientedprogramminglanguag
Wesley13 Wesley13
3年前
IOS全局变量
IOS中的全局变量和JAVA中的全局变量定义和使用方法不一样,在Java中,只需要将变量定义为static就行了。而在IOS中这种方法不适合。IOS中定义全局变量有三种方法:1.使用extern关键字在AppDelegate.m或AppDelegate.h中写入你需要的全局变量名,例如:int name;注意定义全局变量时候不能初始化,否则报错
Wesley13 Wesley13
3年前
Java数组操作的10大方法
0、定义一个Java数组String aArray  new String5;String bArray  {"a","b","c", "d", "e"};String cArray  new String{"a","b","c","d","e"};第一种是定义了一个数组
Stella981 Stella981
3年前
Python中的__new__及其用法
\_\_new\_\_和\_\_init\_\_的区别\_\_new\_\_是Python面向对象语言中一个很少用的函数,更多使用的是\_\_init\_\_这个函数。例如:class Book(object):    def __init__(self, title):
Stella981 Stella981
3年前
C++中vector的使用
在c中,vector是一个十分有用的容器。作用:它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。vector在C标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类(https://www.oschina.net/action/GoToLink?url
Stella981 Stella981
3年前
JNIEnv的使用在C和C++中的区别
对于JNIEnv\env来说,在C中调用:(\env)NewStringUTF(env,"HellofromJNI!");而在C中如果按照上述调用则会发生'baseoperandof''hasnonpointertype'\_JNIEnv''错误,需要如下调用:envNewStringUTF("Hell
Stella981 Stella981
3年前
Magento Block的几种调用方式
MagentoBlock的三种显示方式1。最常见的一种方式:在layout文件中配置,然后在.phtml模板文件中输出。<cms_page<referencename"content"<blocktype"cms/page"name"cms_page"</block</
Stella981 Stella981
3年前
QT中手动释放堆中的对象(new 出来的)
Qt内存自动释放有两个前提条件:1.必须是QObject的派生类2.必须指定了parent对象即:Qt中父亲被删除的时候会自动销毁他的孩子。所以如果New出来的并且没有父亲。那么则需要手动删除它。需要,不然那块空间就一直占用了QLabellbnewQLabel();delete(lb);if(lbN
Stella981 Stella981
3年前
Python类中的__new__和__init__的区别
在写Python类时,或者看某些项目源码时,总是见到__init__和__new__方法,一直没有深入研究两者的区别,今天聊聊这个。__new____new__是类(class)方法。class新创建实例时,会调用__new__,它主要控制一个新实例的创建。需要知道的是,__new__是实例创建的第
融资困难
融资困难
Lv1
刷羽同摇漾,一举还故乡。
文章
3
粉丝
0
获赞
0