C++中的new和delete

C++中的new/delete运算符有两种含义:

1.  new/delete operator,内置的运算符(即newdelete这两个keywords),用来分配内存(需要调用2中描述的运算符)并初始化变量/对象(调用构造函数等)。

2.  operator new/delete,用来进行内存分配和回收的运算符,只负责内存的分配和回收。

看下面的例子:

class MyClass {…};

MyClass *p = new MyClass; // there should be a default constructor in MyClass

 

这个例子中的 new1中描述的运算符。实际上它执行如下3个过程:

1).  调用2中描述的new算符分配内存;

2).  调用构造函数完成对象的创建和初始化(因为需要完成ctor和dtor的自动调用,所以C++新增了new和delete这两个关键字,C中的malloc()和free()是函数,无法完成这样的任务);

3).  返回相应的指针。

2中描述的算符在C++中有3种定义,下面的代码片段摘自new文件(CentOS 5.4, /usr/include/c++/4.1.2/new)。

// plain new/delete

// 带抛出异常的版本

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

void* operator new[](std::size_t) throw (std::bad_alloc);

void operator delete(void*) throw();

void operator delete[](void*) throw();

 

// nothrow new/delete

// 不抛出异常的版本

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

void* operator new[](std::size_t, const std::nothrow_t&) throw();

void operator delete(void*, const std::nothrow_t&) throw();

void operator delete[](void*, const std::nothrow_t&) throw();

 

// Default placement versions of operator new.

inline void* operator new(std::size_t, void* __p) throw() { return __p; }

inline void* operator new[](std::size_t, void* __p) throw() { return __p; }

 

// Default placement versions of operator delete.

inline void  operator delete  (void*, void*) throw() { }

inline void  operator delete[](void*, void*) throw() { }

 

因为1中描述的new/delete最终会调用2中描述的new/delete,而2中提及的new/delete共有上述3种版本,那么1中提及的new/delete(主要是new)则有3种调用方式。(补充:new operator的3种调用方式用来告诉编译器调用哪个operator new,而delete operator则只有一种调用方式,operator delete的3个版本主要是给编译器使用的,如构造函数抛出异常时调用operator new对应的operator delete来释放内存。)

// 1. plain new

try

{

char *p = new char[10000000];

delete []p;

}

catch (const std::bad_alloc &ex)

{

    cout << ex.what() << endl;

}

 

// 2. nothrow new

char *p = new(nothrow) char[10000000];

if (NULL == p) cout << “allocation failed!” << endl;

delete []p;

 

// 3. placement new

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

if (NULL == p)

{

cout << “allocation failed!” << endl;

exit(-1);

}

long *q = new(p) long(1000);

delete []p;

 

为了证明1中提及的new/delete的工作方式,来看下面的演示代码:

#include <iostream>

 

using namespace std;

 

class Demo

{

public:

       Demo() : __x(0)

       {

              static int counter = 0;

              cout << "default ctor is called: " << ++counter << endl;

       }

 

       ~Demo()

       {

              static int counter = 0;

              cout << "dtor is called: " << ++counter << endl;

       }

 

       // 这里我们对global作用域中带异常抛出版本的new/delete进行重载

       static void* operator new(std::size_t) throw (std::bad_alloc);

       static void* operator new[](std::size_t) throw (std::bad_alloc);

 

       static void operator delete(void*) throw();

       static void operator delete[](void*) throw();

 

private:

       int __x;

};

 

void* Demo::operator new(std::size_t size) throw (std::bad_alloc)

{

       cout << "operator new is called, size = " << size << endl;

 

       // 此处我们直接调用global作用域中的new

       return ::operator new(size);

}

 

void* Demo::operator new[](std::size_t size) throw (std::bad_alloc)

{

       cout << "operator new[] is called, size = " << size << endl;

 

       // 此处我们直接调用global作用域中的new[]

       return ::operator new[](size);

}

 

void Demo::operator delete(void *p) throw()

{

       cout << "operator delete is called" << endl;

 

       // 此处我们直接调用global作用域中的delete

       ::operator delete(p);

}

 

void Demo::operator delete[](void *p) throw()

{

       cout << "operator delete[] is called" << endl;

 

       // 此处我们直接调用global作用域中的delete[]

       ::operator delete[](p);

}

 

int main(void)

{

       try

       {

              Demo *p = new Demo;

              delete p;

 

              Demo *pa = new Demo[3];

              delete []pa;

       }

       catch(const std::bad_alloc &ex)

       {

              cout << ex.what() << endl;

       }

 

       return 0;

}

 

程序的输出结果如下(CentOS 5.4, g++ 4.1.2):

operator new is called, size = 4

default ctor is called: 1

dtor is called: 1

operator delete is called

 

operator new[] is called, size = 16 (猜猜这里为什么是16)

default ctor is called: 2

default ctor is called: 3

default ctor is called: 4

dtor is called: 2

dtor is called: 3

dtor is called: 4

operator delete[] is called

 

从上面的输出可以看出当new一个对象的时候,重载的operator new会先被调用,然后是构造函数;delete一个对象时,则先调用析构函数,然后调用重载的operator delete

 

 

原文链接: https://www.cnblogs.com/zhtwe/archive/2011/01/05/2159000.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    C++中的new和delete

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/19671

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月7日 下午8:58
下一篇 2023年2月7日 下午8:59

相关推荐