为什么删除 void* 是 UB 而不是编译错误?
Why deleting void* is UB rather than compilation error?
为什么通过 void*
删除对象是未定义的行为,而不是编译错误?
void foo(void* p) {
delete p;
}
此代码编译并生成代码,尽管在 gcc 和 clang 上有警告(令人惊讶的是,ICC 没有给出警告):
:2:5: warning: cannot delete expression with pointer-to-'void'
type 'void *' [-Wdelete-incomplete]
为什么不只是格式错误的语法无效的程序?看起来 Standard 并没有花太多时间在上面,在 [expr.delete]
中说
This implies that an object cannot be deleted using a pointer of type
void* because void is not an object type.
为什么我会遗漏这不会触发硬编译错误的原因?
在现代 C++ 中,删除 void *
指针 是 错误格式(即我们通常称之为 "compilation error")
8.3.5 Delete
1 [...] The operand shall be of pointer to object type or of class type.
void *
不是指向对象类型的指针。
在 C++98 中,情况有所不同。删除 void *
类型的空指针是 NOP,而删除 void *
类型的非空指针是 UB。
规范中的这一更改似乎是由 defect report #599 触发的。原始规范允许在 delete-expression 中提供 any 指针类型的空指针,例如函数指针。这看起来过于宽容了。 DR#599 的决议收紧了要求,同时取缔了 void *
。
为什么通过 void*
删除对象是未定义的行为,而不是编译错误?
void foo(void* p) {
delete p;
}
此代码编译并生成代码,尽管在 gcc 和 clang 上有警告(令人惊讶的是,ICC 没有给出警告):
:2:5: warning: cannot delete expression with pointer-to-'void' type 'void *' [-Wdelete-incomplete]
为什么不只是格式错误的语法无效的程序?看起来 Standard 并没有花太多时间在上面,在 [expr.delete]
中说
This implies that an object cannot be deleted using a pointer of type void* because void is not an object type.
为什么我会遗漏这不会触发硬编译错误的原因?
在现代 C++ 中,删除 void *
指针 是 错误格式(即我们通常称之为 "compilation error")
8.3.5 Delete
1 [...] The operand shall be of pointer to object type or of class type.
void *
不是指向对象类型的指针。
在 C++98 中,情况有所不同。删除 void *
类型的空指针是 NOP,而删除 void *
类型的非空指针是 UB。
规范中的这一更改似乎是由 defect report #599 触发的。原始规范允许在 delete-expression 中提供 any 指针类型的空指针,例如函数指针。这看起来过于宽容了。 DR#599 的决议收紧了要求,同时取缔了 void *
。