调用析构函数方法比较
我只是想知道这三种调用析构函数的方法是否有任何显着/严重的差异。考虑以下代码。另请考虑 main()
中提到的两种情况。
class Sample
{
public:
~Sample()
{
cout << "destructor called" << endl;
}
void destroyApproach1() { this->~Sample(); }
void destroyApproach2() { delete this; }
};
void destroyApproach3(Sample *_this)
{
delete _this;
}
void TestUsingNew()
{
Sample *pSample[] = { new Sample(), new Sample(),new Sample()};
pSample[0]->destroyApproach1();
pSample[1]->destroyApproach2();
destroyApproach3(pSample[2]);
}
void TestUsingPlacementNew()
{
void *buf1 = std::malloc(sizeof(Sample));
void *buf2 = std::malloc(sizeof(Sample));
void *buf3 = std::malloc(sizeof(Sample));
Sample *pSample[3] = { new (buf1) Sample(), new (buf2) Sample(), new (buf3) Sample()};
pSample[0]->destroyApproach1();
pSample[1]->destroyApproach2();
destroyApproach3(pSample[2]);
}
int main()
{
//Case 1 : when using new
TestUsingNew();
//Case 2 : when using placement new
TestUsingPlacementNew();
return 0;
}
回复时请具体说明您要回答哪种情况:情况 1 或情况 2,或两者兼而有之!
另外,我试图以这种方式编写 TestUsingPlacementNew()
,但它抛出运行时异常(MSVC++2008)。我不明白为什么:
void TestUsingPlacementNew()
{
const int size = sizeof(Sample);
char *buffer = (char*)std::malloc( size * 3);
Sample *pSample[] = { new (buffer) Sample(), new (&buffer[size]) Sample(),new (&buffer[2*size]) Sample()};
pSample[0]->destroyApproach1();
pSample[1]->destroyApproach2();
destroyApproach3(pSample[2]);
}
也许内存填充和/或对齐可能是原因?
相关主题:销毁对象放置新后未调用析构函数
I'm just curious to know if there is any significant/serious difference in these three approaches of invoking destructor. Consider the following code. Please also consider the two cases mentioned in main()
.
class Sample
{
public:
~Sample()
{
cout << "destructor called" << endl;
}
void destroyApproach1() { this->~Sample(); }
void destroyApproach2() { delete this; }
};
void destroyApproach3(Sample *_this)
{
delete _this;
}
void TestUsingNew()
{
Sample *pSample[] = { new Sample(), new Sample(),new Sample()};
pSample[0]->destroyApproach1();
pSample[1]->destroyApproach2();
destroyApproach3(pSample[2]);
}
void TestUsingPlacementNew()
{
void *buf1 = std::malloc(sizeof(Sample));
void *buf2 = std::malloc(sizeof(Sample));
void *buf3 = std::malloc(sizeof(Sample));
Sample *pSample[3] = { new (buf1) Sample(), new (buf2) Sample(), new (buf3) Sample()};
pSample[0]->destroyApproach1();
pSample[1]->destroyApproach2();
destroyApproach3(pSample[2]);
}
int main()
{
//Case 1 : when using new
TestUsingNew();
//Case 2 : when using placement new
TestUsingPlacementNew();
return 0;
}
Please be specific when replying as to which case you're answering to : case 1 or case 2, or both!
Also, I was trying to write TestUsingPlacementNew()
in this way, but it's throwing runtime exception (MSVC++2008). I don't understand why:
void TestUsingPlacementNew()
{
const int size = sizeof(Sample);
char *buffer = (char*)std::malloc( size * 3);
Sample *pSample[] = { new (buffer) Sample(), new (&buffer[size]) Sample(),new (&buffer[2*size]) Sample()};
pSample[0]->destroyApproach1();
pSample[1]->destroyApproach2();
destroyApproach3(pSample[2]);
}
Maybe, memory padding and/or alignment could be the reason?
Related topic : Destructor not called after destroying object placement-new'ed
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,这些方法之间存在巨大差异:
在destroyApproach1中,您只调用对象的析构函数;您实际上并没有释放它占用的内存。
在
destroyApproach2
和destroyApproach3
中,您调用对象的析构函数并释放该对象占用的内存(通过使用>删除
表达式)。在第一个TestUsingPlacementNew
测试中,这两种方法也是错误的,因为对象占用的内存最初是通过调用malloc
分配的,而不是通过new
分配的。代码>.上次测试中出现运行时错误是因为您尝试
删除
数组中索引1
处的对象;指向该元素的指针最初并不是通过调用 new 获得的。在第一个示例中,它仅“有效”(其中“有效”实际上意味着“行为未定义,但它似乎仍然可以正确运行),因为所有三个指针都指向独立的堆分配。Yes, there is a huge difference between these approaches:
In
destroyApproach1
, you only call the destructor of the object; you don't actually free the memory that it occupied.In
destroyApproach2
anddestroyApproach3
you call the destructor of the object and you free the memory that the object occupied (by using thedelete
expression). In the firstTestUsingPlacementNew
test, both of these are also wrong since the memory occupied by the object was initially allocated by a call tomalloc
, not bynew
.The runtime error in your last test occurs because you attempt to
delete
the object at index1
in the array; the pointer to that element was not initially obtained from a call tonew
. In the first example, it only "works" (where "works" really means "the behavior is undefined but it still appears to function correctly) because all three pointers are to independent heap allocations.delete this
不是在现代代码中调用析构函数的正确方法。一般来说,您不必调用析构函数:它们的魔力在于它们在适当的时间被调用:在所有情况下,
delete
都是为了释放由new
分配的内存。当对象不是由new
分配时,delete this
将会导致麻烦:这将使您的程序在几乎所有具有实际操作系统的平台上崩溃(“几乎所有”,因为这在技术上是未定义的行为,并且在这种情况下,允许符合标准的程序损坏自身并继续运行,请祈祷您的平台所做的不仅仅是让您在损坏的内存管理数据结构和无效堆栈中蹒跚而行。
放置
new
主要用于硬件设备驱动程序或其他必须在特殊地址分配指针的地方。 一般来说,您不想销毁通过放置分配的对象新
。如果您愿意,只需直接调用析构函数:但是,请记住,Bjarne Stroustrup 说:“应尽可能避免显式调用析构函数。有时,它们是必要的。...新手应该三思而后行。显式调用析构函数,并在这样做之前询问更有经验的同事”(C++ 编程语言,10.4.11)。
delete this
is not the correct way to call a destructor in modern code. In general you shouldn't have to call the destructor: their magic is that they are called at the appropriate time:delete
in all cases is for releasing memory allocated bynew
.delete this
will then cause trouble when the object was not allocated bynew
:This will crash your program on almost all platforms with an actual operating system ("almost all" because this is technically undefined behavior and a standards-compliant program is allowed to corrupt itself and continue running in this case, keep your fingers crossed that your platform does more than let you hobble along with corrupted memory management data structures and an invalid stack).
Placement
new
is largely meant for hardware device drivers or other places where a pointer must be allocated at a special address. In general you won't want to destroy objects allocated with placementnew
. In cases where you want to, simply call the destructor directly:But, remember, Bjarne Stroustrup said, "explicit calls of destructors ... should be avoided wherever possible. Occasionally, they are essential. ... A novice should think thrice before calling a destructor explicitly and also ask a more experienced colleague before doing so" (The C++ Programming Language, 10.4.11).