如何删除空指针?

41

像这样在C++中删除对象时是否存在任何问题?

MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;

16
将指针转换为 void* 类型,然后再转回其原始类型,可以保证其值不变。 - David Schwartz
3
将类型为“指向对象的指针”转换为“指向const void的指针”,再将其转换回原始类型,即使cv限定符发生变化,也必须保留原始值。 - Tony Delroy
6
为什么你想要这样做? - Jack Aidley
@Jack Aidley,因为我想在C中使用C++类,所以必须使用void指针。 - user3277361
4
我觉得你可能应该发布一个更详细的问题,概述你正在做什么以及原因,因为如果那是情况的话,我强烈怀疑你的方式不太理想。 - Jack Aidley
@DavidSchwartz:然而它并没有说明转换后的值是什么。对于其他转换,如“类型为float的rvalue可以转换为类型为double的rvalue。值不变”,它明确地说明了这一点。 - Engineer2021
3个回答

75

这段代码是合法的。

将其转换回是关键。如果没有这个,您将调用未定义的行为--MyCls析构函数将不会被调用,并且可能会出现其他问题(如崩溃)。您必须向正确的类型进行强制转换。

还要注意,如果涉及多重继承并使用多个转换,则可能会变得复杂。您的转换必须“匹配”。

如果您的代码结构使您无法在销毁时知道类型,请将每个可删除对象都赋予具有虚析构函数的公共基类。然后在调用delete之前将其转换回基类。


通过 delete void* 或 delete 基类,如何推断内存大小需要释放? - ryanafrish7

35

代码定义良好。两个转换都是静态转换,尽管显式地使用static_cast<void*>等方法而不是使用C样式转换更好。标准规定,如果将对象指针通过静态转换转换为void指针,然后再通过静态转换转换回来,它将保留其原始值。因此,您的最终delete表达式应具有与delete c相同的效果。

话虽如此,在C++中使用void*通常是一种代码异味。


4
避免使用C样式强制转换,这个建议非常好。它们往往会比你预期的执行更多操作。 - StilesCrisis
4
比如说,更糟的情况是你得到的结果比你原本预期的还要 - fluffy
2
避免使用 void* 是一个好建议。我有很多故事,都是因为之前的 Java 程序员期望 delete someVoidPointer; 能够正常工作而导致的后续清理工作。 - fluffy

0

虽然这段代码是有效的,但它不是一个好的实践。

一般来说,在代码中不应该出现 newdelete。尝试强制规定只有构造函数可以调用 new,只有析构函数可以调用 delete,将有助于更好地组织您的代码。

如果您正在使用 C++11,请始终尝试使用 std::shared_ptr 等,这将自动为您执行上述操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接