首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >手动调用析构函数总是糟糕设计的标志吗?

手动调用析构函数总是糟糕设计的标志吗?
EN

Stack Overflow用户
提问于 2013-01-07 05:33:21
回答 9查看 112.8K关注 0票数 87

我在想:他们说如果你手动调用析构函数--你做错了什么。但情况总是这样吗?有什么反例吗?需要手动调用它,或者很难/不可能/不切实际地避免它的情况?

EN

回答 9

Stack Overflow用户

回答已采纳

发布于 2013-01-07 05:39:29

如果对象是使用operator new()的重载形式构造的,则需要手动调用析构函数,除非使用"std::nothrow“重载:

T* t0 = new(std::nothrow) T();
delete t0; // OK: std::nothrow overload

void* buffer = malloc(sizeof(T));
T* t1 = new(buffer) T();
t1->~T(); // required: delete t1 would be wrong
free(buffer);

然而,在外部管理内存的级别相当低,就像上面显式调用析构函数一样,这是一个糟糕设计的标志。可能,它实际上不仅仅是糟糕的设计,而且是完全错误的(是的,在赋值操作符中使用显式析构函数,然后调用复制构造函数是一个糟糕的设计,而且很可能是错误的)。

对于C++ 2011,使用显式析构函数调用还有另一个原因:当使用广义联合时,有必要显式销毁当前对象,并在更改表示对象的类型时使用placement new创建一个新对象。此外,当联合被销毁时,如果当前对象需要销毁,则有必要显式调用当前对象的析构函数。

票数 99
EN

Stack Overflow用户

发布于 2013-01-07 06:19:01

所有的答案都描述了特定的情况,但有一个通用的答案:

每次只需要销毁对象(在C++意义上)而不释放对象所在的内存时,都会显式地调用dtor。

在内存分配/释放独立于对象构造/销毁进行管理的所有情况下,通常都会发生这种情况。在这些情况下,通过在现有内存块上放置new进行构造,并通过显式dtor调用进行销毁。

下面是一个原始的例子:

{
  char buffer[sizeof(MyClass)];

  {
     MyClass* p = new(buffer)MyClass;
     p->dosomething();
     p->~MyClass();
  }
  {
     MyClass* p = new(buffer)MyClass;
     p->dosomething();
     p->~MyClass();
  }

}

另一个值得注意的例子是std::vector使用的默认std::allocator:元素是在push_back期间在vector中构造的,但内存是以块为单位分配的,因此它预先存在元素构造。因此,vector::erase必须销毁元素,但不一定要释放内存(特别是在新的push_back必须很快发生的情况下…)。

在严格的OOP意义上,它是“糟糕的设计”(你应该管理对象,而不是内存:对象需要内存的事实是一个“事件”),它是“低层编程”中的“好设计”,或者是在内存不是从默认operator new购买的“免费存储”中获得的情况下。

如果它在代码周围随机发生,那就是糟糕的设计,如果它发生在专门为此目的而设计的类的本地,那就是好的设计。

票数 114
EN

Stack Overflow用户

发布于 2013-01-07 05:35:44

不,你不应该显式调用它,因为它会被调用两次。一次用于手动调用,另一次是在声明对象的范围结束时。

例如:

{
  Class c;
  c.~Class();
}

如果你真的需要执行同样的操作,你应该有一个单独的方法。

有一个specific situation,您可能想要使用放置new调用动态分配的对象上的析构函数,但它听起来并不是您所需要的。

票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14187006

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档