深入 C++的 new
“new”是 C++的一个关键字,同时也是操作符。关于 new 的话题非常多,因为它确实比较
复杂,也非常神秘,下面我将把我了解到的与 new 有关的内容做一个总结。
new 的过程
当我们使用关键字 new 在堆上动态创建一个对象时,它实际上做了三件事:获得一块内存
空间、调用构造函数、返回正确的指针。当然,如果我们创建的是简单类型的变量,那么
第二步会被省略。假如我们定义了如下一个类 A:
class A
{
int i;
public:
A(int _i) :i(_i*_i) {}
void Say() { printf("i=%dn", i); }
};
//调用 new:
A* pa = new A(3);
那么上述动态创建一个对象的过程大致相当于以下三句话(只是大致上):
A* pa = (A*)malloc(sizeof(A));
pa->A::A(3);
return pa;
虽然从效果上看,这三句话也得到了一个有效的指向堆上的 A 对象的指针 pa,但区别在于,
当 malloc 失败时,它不会调用分配内存失败处理程序 new_handler,而使用 new 的话会的。
因此我们还是要尽可能的使用 new,除非有一些特殊的需求。
new 的三种形态
到目前为止,本文所提到的 new 都是指的“new operator”或称为“new expression”,但事实上
在 C++中一提到 new,至少可能代表以下三种含义:new operator、operator new、placement
new。
new operator 就是我们平时所使用的 new,其行为就是前面所说的三个步骤,我们不能更改
它。但具体到某一步骤中的行为,如果它不满足我们的具体要求时,我们是有可能更改它
的。三个步骤中最后一步只是简单的做一个指针的类型转换,没什么可说的,并且在编译
出的代码中也并不需要这种转换,只是人为的认识罢了。但前两步就有些内容了。
new operator 的第一步分配内存实际上是通过调用 operator new 来完成的,这里的 new 实际
上是像加减乘除一样的操作符,因此也是可以重载的。operator new 默认情况下首先调用分
配内存的代码,尝试得到一段堆上的空间,如果成功就返回,如果失败,则转而去调用一
个 new_hander ,然后继续重复 前面过程 。如果我 们对这个 过程不满 意,就可 以重载
operator new,来设置我们希望的行为。例如:
class A
{
public:
void* operator new(size_t size)
{
printf("operator new calledn");
return ::operator new(size);
评论2