【发布时间】:2015-11-24 14:23:15
【问题描述】:
已经在 stackoverflow 上就这个主题提出了一些问题,但我还没有看到任何解释删除表达式限制背后的基本原理。
为了澄清这个主题,我试图收集我在以下三个评论中理解的事实。
备注1:通用新表达式
让我们考虑任何“新操作符”(无论它是默认全局操作符、覆盖默认全局操作符的版本、重载版本还是类成员版本)。假设我们也有一个匹配的“operator delete”。
假设原型如下:
void* operator new(size_t, T1, T2, ..., Tn);
void operator delete(void*, T1, T2, ..., Tn);
我们知道当程序员键入一个新的表达式时:
T* t = new(t1, ..., tn) T();
(其中t1, ..., tn的类型分别为T1, ... Tn)
编译器会自动将这一行替换为:
T* t;
void* raw = operator new(sizeof(T), t1, ..., tn); // or T::operator new(...)
try {
t = new(raw) T();
}
catch (...) {
operator delete(raw, t1, ..., tn); // or T::operator delete(...)
throw;
}
备注 2:删除表达式 - 在某些情况下是合法的
我们知道,当程序员键入这个删除表达式时:
delete t;
(其中 t 的类型是 T)
编译器会自动将这一行替换为:
if (t) {
t->~T();
operator delete(t); // or T::operator delete(t);
}
因此,我们知道使用简单的语法“delete t;”我们可以隐式自动调用任何与默认全局参数具有相同参数的“操作符删除”(它可以是默认全局参数本身、覆盖默认全局参数的版本或类成员版本,其参数与默认全局参数相同)。
备注 3:删除表达式 - 一般是非法的
让我们考虑任何不采用与默认全局参数相同的参数的“操作符删除”(它可以是全局重载版本或类成员版本)。
假设原型如下:
void operator delete(void*, T1, ..., Tn);
我们本来想写一个通用的删除表达式:
delete(t1, ..., tn) t;
希望编译器会自动将其替换为:
if (t) {
t->~T();
operator delete(t, t1, ..., tn); // or T::operator delete(...);
}
...,不幸的是我们知道 "delete(t1, ..., tn) t;"是非法的!
因此,通常建议编写如下模板函数:
template<typename T> void destroy(T* t, T1 t1, ..., Tn tn) {
if(t) {
p->~T();
operator delete(t, t1, ..., tn); // or T::operator delete(...); ?!
}
}
这可能有问题(您必须为每个“操作符删除”定义一个,并且您必须小心,因为您无法以相同的方式处理全局版本和类成员版本)。
总结一下:
我们有一个通用的新表达式,但没有通用的删除表达式。
您知道出现这种不一致的原因吗?
【问题讨论】:
-
你能详细说明一下备注1吗?我看不到 (cplusplus.com/reference/new/operator%20new) 任何代码,例如
void* operator new(size_t, T1, T2, ..., Tn); -
@RomanZaytsev 这个原型代表了任何可能的“operator new”。例如,它可以表示用户定义的重载版本。
标签: c++ memory-management delete-operator