C++中的new/delete运算符有两种含义:
1. new/delete operator,内置的运算符(即new和delete这两个keywords),用来分配内存(需要调用2中描述的运算符)并初始化变量/对象(调用构造函数等)。
2. operator new/delete,用来进行内存分配和回收的运算符,只负责内存的分配和回收。
看下面的例子:
class MyClass {…}; MyClass *p = new MyClass; // there should be a default constructor in MyClass |
这个例子中的 new是1中描述的运算符。实际上它执行如下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】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/19671
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!