显式删除析构函数而不调用delete
我正在阅读C ++ 11 FAQ,并注意到这一点:
class X4 {
~X4() = delete; // Disallow destruction
}
这隐含地也禁止移动X4。 复制是允许的,但不推荐使用。
我也发现了这句话。
删除析构函数的定义将需要在free-store上进行分配,因为静态和自动对象会隐式地调用析构函数:``
struct C
{
~C()= delete; //prevent automatic and static objects
};
但是,这种技术并不像看起来那么有用,因为它可以防止删除表达式。 尽管单身对象可以使用它
这是有道理的。 我的问题是,是否有一个Singleton的显式删除析构函数被认为是好的做法? 此外,如果有人知道任何其他情况下你不应该打电话delete
,请让我知道。
实际上,你有时会发现自己处于不安全的情况下销毁特定类型的对象。 所以你应该删除析构函数来防止任何人尝试。
在Singleton的情况下,只有一个类型的实例,如果没有清除实例的负载,未能销毁它可能不那么有害。
Singletons(或任何其他全局可用的对象)的问题之一是,您可能会失去对它们的依赖关系的控制。 那么很难确定一个安全的销毁顺序 - 如果全局数据库对象记录到已经安全关闭连接的全局记录器对象,但是可以选择全局记录器对象通过全局数据库对象记录到数据库,那么你有一个问题。
虽然你可以通过不破坏全局数据库对象来“解决”这个问题,但我认为这不应该被称为“良好实践”。 这听起来更像是一种处理不好的情况而不用重新设计的简单方法(尽管在我的例子中重新设计也可能非常简单 - 只要确保数据库记录器或数据库本身对日志消息有用当连接关闭时,将它们吞下或重定向到另一个可用的目的地)。
可能有“好”的设计,其中一种特定类型的对象不能被销毁,但它不是C ++类设计的常用方式。
此外,如果有人知道任何其他情况下你不应该打电话删除,请让我知道。
内存池的使用是我能想到的一种情况。
在某种情况下,即使对于自动变量,析构函数也不会被调用:当用户写入显式析构函数X::~X
时,析构函数在类X
内的匿名联合体的析构函数。 由于联合是匿名的,因此根本不可能通过X::~X
调用它的析构函数(它现在不会调用析构函数,因为它不知道调用析构函数)。
顺便说一下,在这种情况下,用户无法声明联合析构函数被删除(再次缺少名称),但可以隐式删除它。
奇怪的是,在这种情况下,默认的析构函数X::~X
会调用匿名函数的析构函数。 但是,只要允许,这是一个纯粹的形式问题,析构函数调用不起作用。 这是因为只有联盟的所有变体都有微不足道的析构函数(因此也是工会本身)才允许这样做。 如果它们中的任何一个具有非平凡的析构函数,则联合的析构函数被隐式地删除,使X
的默认析构函数无法操作(有效地被删除)。
然而,这并不意味着不能使用包含匿名联合的类X
与至少一个具有非平凡析构函数的成员。 这意味着用户编写的X::~X
必须直接破坏匿名联合的活动变体,绕过联合自身的已删除析构函数。 这是可能的,只要该类包含允许了解哪个变体处于活动状态的其他成员。 类似的X
构造函数应该直接构造联合的至多一个变体,绕过匿名联合(可能被删除)的构造函数(除非变体是POD,这样的构造函数不应该直接赋值给联合变体)。 事实上,匿名联合的特殊成员函数是一种幽灵实体,它不是非平凡的,它的唯一作用是可能被删除,以便将删除的状态有效地传播给包含X
的相应特殊成员函数。