【发布时间】:2021-06-04 02:49:28
【问题描述】:
前言:我正在优化旧代码库。
我有一个名为 Token 的类,我为它添加了缓存以用于令牌的子集(但不是全部)。缓存的令牌可能不会被删除,因为它们的指针在程序的整个生命周期内都存储在内存中的永久集合中。
不幸的是,代码库中到处都是delete token。所以我所做的是添加一个bool cached 成员,该成员从Token::operator delete 内部检查和析构函数~Token(),如果cached 为真,则立即从这些各自的函数返回。
我的问题是,这是未定义的行为,还是我可以这样做?可以对不会被删除的东西执行delete 运算符吗?或者这会在将来咬我吗?
class Token
{
bool cached;
void* data;
public:
~Token()
{
if (this->cached) return;
free(data);
}
void operator delete(void* p)
{
if (((Token*)p)->cached) return;
::operator delete(p);
}
// operator new, constructor etc.
}
【问题讨论】:
-
添加您的
Token类的最小示例... -
在
~Token()内部检查cached是没有用的,因为到那时该对象已经处于被销毁的过程中。 -
我添加了一个例子来澄清事情。尽管现在我突然想到,如果该类包含具有自己的析构函数的对象,它们将被销毁,对此我无能为力(这里不是这种情况,但仍然如此)。 @RemyLebeau 如果我没记错的话,析构函数是在运算符删除之前调用的?
-
那么,真正的目标不是阻止
Token对象的销毁,而是它们内部包含的data的销毁?这与您最初提出的问题完全不同。如果是这种情况,您可能根本不需要重载运算符。看到minimal reproducible example 演示令牌的实际使用方式会有所帮助。 -
不,你误会了;当缓存为真时,我既不想破坏令牌也不想破坏数据。如果将 operator delete 配置为不释放其背后的底层内存,则不会释放令牌。如果析构函数在释放它之前返回,数据也不会。
标签: c++