关于C++的placement new和placement delete

原创 2012年03月27日 01:03:49

昨天发贴提了个问题,今天总结在这。原帖点击进入,有兴趣可以看看,我呆会儿还会说。

C++的new是语言自定义的操作符,这个操作符的行为包含两件事,而且你不能改变。

第一件事:调用operator new分配内存。所以通常说的重载new函数其实重载的是operator new,你无法重载new。

第二件事:调用你要new的对象的所属类的构造函数初始化第一步中分配的内存。这就是为什么你Object *pobj = new Object后,可以直接使用pobj->调用类中函数的原因。

delete操作符也是类似,不过先调用析构函数,然后释放内存,对应有一个operator delete。


帖子中的代码的目的是重载operator new和operator delete,把new和delete的历史通过一个ostream记录下来。好了,上代码了:

#include <iostream>

using namespace std;

class B{
public:
  B(){cout << "ctor B" << endl;}
  ~B(){cout << "dtor B" << endl;}
  void * operator new(size_t size, ostream& out){
    out << "new B" << endl;
    return ::operator new(size);
  }
  void operator delete(void *mem, ostream& out){
    out << "delete B" << endl;
    ::operator delete(mem);
  }
};

int main(){
  B *pb = new (cout)B;
  B *pb2 = ::new B;
  //delete pb;   这句编译不通过,说no suitable ‘operator delete’ for ‘B’
  ::delete pb2;
}

如果注释那段没问题,这段代码(期望)的输出是:

new B
ctor B
ctor B
dtor B
delete B
dtor B

class B就不解释了,直接看main函数:

  B *pb = new (cout)B; 这句new一个B的对象,因为B类中重载了operator new,所以需要传递一个ostream的对象进去,就像这样传递。如果你这样调用:  B *pb = new B;那是会报错的,因为B类中的operator new把默认的隐藏掉了。这句产生输出:new B ctorB。

  B *pb2 = ::new B; 这句也是new一个B的对象,但是new前面多了两个冒号,意思是调用全局的new,调用了上面说的被隐藏调的operator new。这句产生输出:ctor B。

  delete pb; 这句想要delete掉pb指向的对象,但是失败,原因在后面。这句(期望)输出:dtor B delete B。

  ::delete pb2; 这句delete掉pb2指向的对象,调用全局的delete,没有问题,这句输出:dtor B。


关于delete pb为什么失败:

2楼 RabbitLBJ:

先说声楼主最好还是把new,delete声明称static好些

把出错的行改成如下
B::operator delete(pb,cout);
即可调用到placement delete了,但是想法和楼主的有差距,这函数里面直接释放内存,就不会再析构了
貌似这个delete是不能通过delete关键字在外面调用的,这个一般都是给系统在placement new出错时调用
而且只要有使用placement new,析构一般都是要手动进行的

4楼 pengzhixi:

c++为什么没有内置的"placement new"是因为 没办法提供一个通用的。
B *pb = new (cout)B;当我们写出这样的代码的时候,c++不能推出pb指针里面存放的对象类型。(虽然我们知道是什么类型)。所以不会有placement delete.只有在placement new抛出异常的时候,编译器才会调用placement delete.这个时候因为构造不成功所以只需要负责释放内存即可。所以LZ只能是先显示调用析构函数,然后在显示调用placement delete.

另外:不要重载operator new operator delete这些东西。

这两位朋友解释的很清楚了,我就不画蛇添足了,在此感谢这两位朋友的解答。



Reference:

Scott Meyers. Effective C++ 3rd edition. 2005

Scott Meyers. More Effective C++ . 1996

关于new delete和placement new,placement delete

问题: 在看stl源码的时候,发现new 还可以这么调用: T* tmp = (T*)(::operator new((size_t)(sizeof(T) * n))); 这个调用很类似于mal...
  • ccjjnn19890720
  • ccjjnn19890720
  • 2013年05月10日 08:52
  • 1271

控制内存分配----重载new和delete & 定位new表达式

定位new表达式, 重载new和delete, 控制内存分配
  • qianqin_2014
  • qianqin_2014
  • 2016年05月05日 11:17
  • 797

placement delete

一个new的过程大致分两步:- 申请内存- 调用构造函数构造新对象如果第一步成功而第二步失败,一个成熟的系统应该能回撤第一步,释放刚分配的内存空间。如果第一步用的是普通的new函数,C++是能够找到与...
  • enjolras
  • enjolras
  • 2010年11月21日 10:37
  • 1045

[翻译] Effective C++, 3rd Edition, Item 52: 如果编写了 placement new,就要编写 placement delete

Item 52: 如果编写了 placement new,就要编写 placement delete作者:Scott Meyers译者:fatalerror99 (iTePubs Nirvana)发布...
  • fatalerror99
  • fatalerror99
  • 2007年01月21日 22:18
  • 6781

c++ placement new操作符的使用技巧

在c++中new和delete操作是我们操作内存最常用的一对操作符,在使用new时编译器会申请内存,然后调用类的构造函数来初始化对象,调用delete会销毁对象同时释放该对象占用的内存,并且我们可以重...
  • D_Guco
  • D_Guco
  • 2017年01月04日 23:18
  • 1112

C++ Placement语法解析[译]

Placement syntax From Wikipedia, the free encyclopedia   (Redirected from Placement new) ...
  • origin_lee
  • origin_lee
  • 2014年11月10日 13:33
  • 368

placement new和placement delete(重载new和delete2)

placement new和placement delete参考:《Effective C++》placement new和placement delete 1 什么是placement new和pl...
  • sanoseiichirou
  • sanoseiichirou
  • 2015年11月21日 11:30
  • 372

条款52:写了placement new也要写placement delete

      当你在写一个new表达式像这样:            Widget* new_widget = new Widget;      共有两个函数被调用:一个是用以分配内存的operator...
  • beecindy
  • beecindy
  • 2010年04月12日 11:09
  • 287

停机测试:我停止了CRS 测试

停机测试: 问题 我停止了CRS 测试。 [grid@m2 ~]$ crs_stat -t CRS-0184: Cannot communicate with the CRS daemon. ...
  • u010098331
  • u010098331
  • 2016年03月02日 19:11
  • 314

沫沫大神的docker入门手册

放在csdn查看markdown文件方便才使用的
  • qq_35049196
  • qq_35049196
  • 2018年01月04日 15:35
  • 331
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于C++的placement new和placement delete
举报原因:
原因补充:

(最多只允许输入30个字)