关于C++的placement new

High_High 2012-03-26 03:38:46
上代码了,问题是如何调用自己定义的delete:

#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

期望输出是:
new B
ctor B
ctor B
delete B
dtor B
dtor B
...全文
437 31 打赏 收藏 转发到动态 举报
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
ZongShengLee 2012-03-26
  • 打赏
  • 举报
回复
http://en.cppreference.com/w/cpp/memory/new/operator_new
bsnry 2012-03-26
  • 打赏
  • 举报
回复

20 楼


[Quote=引用 22 楼 lou0378 的回复:]

当你重载了new 或delete的时候,如果没有特别指明调用的是重载的还是库文件中的,那么默认调用你重载new 或delete,当你重载了placement delete时,只有当new抛出异常时,才调用你重载的placement delete,

如果重载了new,一定要重载相应的delete,

比如楼主写的程序,重载了new,但没有重载相应的delete,虽然重载了placemen……
[/Quote]
High_High 2012-03-26
  • 打赏
  • 举报
回复
问题已解决,主要参考2楼和4楼。
pathuang68 2012-03-26
  • 打赏
  • 举报
回复
强烈建议楼主去看看C++ Primer中的相关章节
  • 打赏
  • 举报
回复
当你重载了new 或delete的时候,如果没有特别指明调用的是重载的还是库文件中的,那么默认调用你重载new 或delete,当你重载了placement delete时,只有当new抛出异常时,才调用你重载的placement delete,

如果重载了new,一定要重载相应的delete,

比如楼主写的程序,重载了new,但没有重载相应的delete,虽然重载了placement delete,但是这个函数只有在new 抛出异常的时候才被调用,然而编译器却认为你重载了delete,那么当你调用delete pb是,编译器默认调用你重载的void operator delete(void *mem, ostream& out)这个函数,而你调用的
delete pb 和你重载的不相符,会发生编译错误,如果你显示调用delete (cout)pb,也会错误,因为你重载的这个placement delete是只有在抛出异常的时候有系统调用的,
因此你重载了new 一定要重载相应的delete,只有重载了相应的delete就可以了,比如:
void operator delete(void *mem)
{::operator delete(mem);}

重载了相应的delete之后就可以这样调用了,
B *pb = new (cout)B;
delete pb;

再比如你这个:B *pb2 = ::new B;这一条语句调用的是库文件中的new,不是调用你重载的那个new,那么在删除的时候直接使用库中的delete就可以了
High_High 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 chuyoule 的回复:]

#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)
{
……
[/Quote]

破坏原设计意图,和期望输出相差万里,无参考价值。
High_High 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 lou0378 的回复:]

当你重载了new 或delete的时候,如果没有特别指明调用的是重载的还是库文件中的,那么默认调用你重载new 或delete,当你重载了placement delete时,只有当new抛出异常时,才调用你重载的placement delete,

如果重载了new,一定要重载相应的delete,

比如楼主写的程序,重载了new,但没有重载相应的delete,虽然重载了placemen……
[/Quote]

我程序中做的和你说的是一样的。
High_High 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 lou0378 的回复:]

引用 18 楼 high_high 的回复:
引用 15 楼 lou0378 的回复:

我在9楼的时候说错了,10楼说的正确

10楼的代码相当于把注释那句换成 ::delete pb

把注释那句改成: delete pb;而不是::delete pb;

如果你重载了new ,那么一定要重载相应的delete,
[/Quote]
我没重载new,我重载的是operator new和operator delete。
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 high_high 的回复:]
引用 15 楼 lou0378 的回复:

我在9楼的时候说错了,10楼说的正确

10楼的代码相当于把注释那句换成 ::delete pb
[/Quote]
把注释那句改成: delete pb;而不是::delete pb;

如果你重载了new ,那么一定要重载相应的delete,
bsnry 2012-03-26
  • 打赏
  • 举报
回复
placement new 原型:

new( 指针) 构造器(不分配内存)



new (cout)B 这中写法没见过,


[Quote=引用 17 楼 high_high 的回复:]

调用了,参见输出。
引用 16 楼 bsnry 的回复:

placement new 不分配内存,楼主的用法

B* pb =new (cout)B; 调用了它自己写的placement new 了吗?





引用 10 楼 lou0378 的回复:
B *pb = new (cout)B;只有当这个内存分配失败抛出异常的时候,才会调用你重载的这个
placeme……
[/Quote]
High_High 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 pengzhixi 的回复:]

忘记是哪本书上说了不要轻易的重载operator new这些东西了。好像是effective c++吧。所以就听听那些大师的忠告吧。
[/Quote]
不听。
High_High 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 lou0378 的回复:]

我在9楼的时候说错了,10楼说的正确
[/Quote]
10楼的代码相当于把注释那句换成 ::delete pb
High_High 2012-03-26
  • 打赏
  • 举报
回复
调用了,参见输出。
[Quote=引用 16 楼 bsnry 的回复:]

placement new 不分配内存,楼主的用法

B* pb =new (cout)B; 调用了它自己写的placement new 了吗?





引用 10 楼 lou0378 的回复:
B *pb = new (cout)B;只有当这个内存分配失败抛出异常的时候,才会调用你重载的这个
placement delete
void operator delete(v……
[/Quote]
bsnry 2012-03-26
  • 打赏
  • 举报
回复
placement new 不分配内存,楼主的用法

B* pb =new (cout)B; 调用了它自己写的placement new 了吗?





[Quote=引用 10 楼 lou0378 的回复:]
B *pb = new (cout)B;只有当这个内存分配失败抛出异常的时候,才会调用你重载的这个
placement delete
void operator delete(void *mem, ostream& out){
out << "delete B" << endl;
::operator delete(mem);
}
如果你重载了new,一定要……
[/Quote]

  • 打赏
  • 举报
回复
我在9楼的时候说错了,10楼说的正确
pengzhixi 2012-03-26
  • 打赏
  • 举报
回复
忘记是哪本书上说了不要轻易的重载operator new这些东西了。好像是effective c++吧。所以就听听那些大师的忠告吧。
High_High 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 pengzhixi 的回复:]

你声不声明都是static声明为static是让你自己看着更清晰而已。不会产生误会。

大的用场:内存管理越界判断等。如果你觉得你的技术可以达到这个层次了,那么无所谓。但是大多数人对这个东西还没了解到那个程度。
[/Quote]

目前还没有,但是看过相关的内容,感觉可以自己管理内存,很好玩。
谢谢大牛指点。
High_High 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 p569354158 的回复:]

C/C++ code

operator delete();


详解见《more effectiv C++》条款8
[/Quote]

那个是和operator new对应的,但是我用的是new。
High_High 2012-03-26
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 lou0378 的回复:]

//delete pb; 这句编译不通过,说no suitable ‘operator delete’ for ‘B’
::delete pb2;
当你重载了new或delete时,如果不指明调用的是自己重载的还是库文件中的?编译器默认调用的是自己重载的那个版本
[/Quote]

要达到你那个效果,把注释那句改成::delete pb就ok了,不用改那么多代码。
  • 打赏
  • 举报
回复

B *pb = new (cout)B;只有当这个内存分配失败抛出异常的时候,才会调用你重载的这个
placement delete
void operator delete(void *mem, ostream& out){
out << "delete B" << endl;
::operator delete(mem);
}
如果你重载了new,一定要重载相应的delete,你再重载一个一般版本的delete就可以调用delete pb;了;

修改如下:

using namespace std;

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

int main(){
B *pb = new (cout)B;
B *pb2 = ::new B;
delete pb;
::delete pb2;
}


加载更多回复(11)

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧