C++中operator new 和 new operator小结以及对new 和 delete初步理解

最近在看C++ Prime,注意到new 和 delete 并没有原来想象的那么简单。记得上学期学C语言时,学习的sizeof和strlen区别时,有一条为sizeof不是函数在这里,和sizeof类似,new 和delete也不是函数,它们都是C++定义的关键字,通过特定的语法可以组成表达式。我们先看看上面提到的operator new 和 operator delete在C++语言标准库的原型

这两个均是 C++ 标准库函数!C++ Primer 一书上说new 和 delete是不允许重载的,那么这里就不是重载 new 和 delete 表达式(如 operator=就是重载 = 操作符),那么

new operator:

它完成了两件事情
第一,分配足够的内存,用来放置某类型的对象。
第二,调用一个构造函数,为刚才分配的内存中的那个对象设定初始值。new operator调用某个函数,执行必要的内存分配动作,你可以重写或者重载那个函数,改变其行为(能够改变的是用来容纳对象的那块内存的分配行为)。这个函数名称就叫operator new 。
operator new:

其返回类型void*。即返回一个指针,指向一块原始的、未设置初始值的内存。函数中的size_t参数表示需要分配多少内存,你可以将operator new 重载,加上额外的参数,但第一个参数类型必须总是size_t。可以像调用任何其他函数一样调用它。

这里的operator new 将返回指针,它指几一块足够容纳string对象的内存。和malloc一样,operator new 的唯一任务就是分配内存,它不知道什么是构造函数,它只负责分配内存。取得operator new 返回的内存并将之转为一个对象,是new operator的工作。这样,刚才的那段代码

可以这样理解

但是在查资料时,还发现了另一个迷惑的术语 placement new 有时候想直接调用一个构造函数,针对一个已经存在的对象调用其构造函数,并无意义,因为构造函数用来对象初始化,而对象只能只能初始化一次。但是当需要在一些分配好的原始内存上构建对象时,placement new,允许这么做。
例如:

此函数返回指针,指向一个Test对象,它被构造于传递给此函数的一块内存缓存区上。当程序运行到共享内存或者内存I/O映射。这类函数可能是有用的,
因为在那样运用中,对象必须置于特定的地址,或者置于特殊函数分配出来的内存上。
分析函数内部
Test* constructTestInBuffer 只有一个表达式new (buffer) Test(size),这是new operator的用法之一,其中所指定一个额外的自变量(buffer)作为
new operator “隐式调用operator new “时所用。于是,被调用的operator new除了接受”一定要有size_t自变量”之外,还接受了一个void* 参数,指向一
块内存,准备用来接受构造好的对象。这样的operator new 就是所谓的placement new
类似还有:

operator new 的目的是要为对象找到一块内存,然后返回一个指针指向它,在placement new 的情况下,调用者已经知道指向内存的指针了,因为调用
者知道对象应该放在哪里。因此placement new 唯一需要做的就是将它获得的指针再返回。至于没有用到(但一定得有)的size_t参数,之所以不赋予
名称,为的是避免”编译器某物未被使用”的警告。
另外注:placement new 是C++标准程序库的一部分,要使用placement new
得用#include<new>,旧式编译器用 #include<new.h>
了解了placement new 后,我们便能了解new operator和operator new之间的关系。

如果你希望将对象产生于heap,就是要用new operator,它不但分配内存而为该对象调用一个构造函数。
如果你只是打算分配内存,请用operator new,就没有构造函数被调用。
如果你打算在heap object产生自己决定的内存分配方式,请写一个自己的operator new。并使用new operator,它将会自动调用你所写的
operator new。
如果你打算在已经分配(并拥有指针)的内存构造对象,使用placement new 。

delete 与内存释放

为了避免资源泄露,每一个动态分配行为都必须匹配一个相应的释放动作。
函数 operator delete对于内建的delete operator(操作符)就好像

内存释放动作是由operator delete执行的,通常声明如下:

因此 delete ps;
执行的步骤如下:
ps->~string();//调用析造函数
operator delete(ps);//释放对象所占用的内存
如果只打算处理原始的、未设初值的内存,直接operator delete 归还给系统。
即调用operator new取得内存并以operator delete归还系统。
如:

类似与C语言中malloc和free。
但是如果使用了placement new ,在某块内存中产生对象,你应该避免那块内存使用delete operator(操作符)。
因为delete operator会调用operator delete来释放内存,但是该内存所含的对象最初并不是由operator new 分配来的。
placement new只是返回它接收的指针而已。为了抵消该对象的构造函数的影响,使用placement new 时应该直接调用该对象的析构函数。
请看示例:

如上述所示,如果交给placement new的原始内存(raw memory)本身是动态分配而得的,那么最终得释放那块内存,以避免内存泄露
基于单一对象上的已经了解了,但如果是一组对象呢?

1.这里的new 与前面的new 行为类似,但略有不同,这里不能再operator new分配内存,而是以operator new[]负责分配。和operator new 一样,operator new[]也可以被重载。
2.数组的new 与单一对象的new所调用的构造函数不同,数组的new 必须针对数组中每一个对象调用一个构造函数。

同样的,当使用了delete,它也会针对数组中每一个元素调用析构函数,然后再调用operator delete[]释放内存。如:

作者:u010927811 发表于2014-3-28 1:22:18 原文链接
阅读:125 评论:0 查看评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">