使用 void 指针删除在堆中分配的变量是一件坏事吗?

is deleting a variable allocated in heap using void pointer a bad thing?

这段代码有问题吗? 我的意思是删除语句。

int *x = new int;

*x = 13;

void *ptr = x;

delete (int *)ptr;

这段代码没有任何问题,堆上分配的所有内存都是免费的,无论是删除 ptr 还是 x 但不是两者都删除。两个指针都指向内存中的同一个地址,所以这完全没问题;也可以安全地设置 free'd pointers = 0!

#include <iostream>
int main()
{

  int* x = new int;
  *x = 13;
  void* ptr = x;

  std::cout << ptr << '\n'; //prints same address
  std::cout << x << '\n'; //prints same address
  
  delete (int*)ptr;
  //delete x;

  ptr = 0;

}

您没有在代码中的 void 指针上调用 delete。在删除之前,您正在将其变回 int *

进行转换 int * -> void * -> int * 保证返回 int 指针的原始值。因此,您基本上是在 new 返回的相同值上调用 delete。这就是你应该做的。

如果你这样做,问题会有所不同

int *x = new int;
void *ptr = x;
delete ptr;

这里 delete 不知道 ptr 实际上应该指向一个 int,并且无法调用任何属于 int 的析构函数。在 int 的情况下,析构函数可能什么都不做,所以我不能肯定地说代码是无效的,也许更精通 c++ 的人可以参与进来?但是对于其他具有真正析构函数的数据类型,这肯定是个问题。

结尾的小评论:避免new/delete。使用智能指针和容器类。仅使用 new/delete 作为如何编写智能指针的练习。

即使您使用的是 explicit type conversion, the rules for static_cast apply. The relevant rule is in point 10 of the static_cast page @ cppreference.com:

Conversion of any pointer to pointer to void and back to pointer to the original (or more cv-qualified) type preserves its original value.

在您的例子中,您从指向 int 的指针开始。当您初始化 ptr 时,您将其转换为指向 void 的指针。您在 delete 语句中转换回指向 int 的指针。这保留了原始值,这意味着 (int *)ptrx 计算出相同的地址(并且具有相同的类型),因此

delete (int *)ptr;

delete x;

是等价的。 (我还要添加

delete static_cast<int*>(ptr);

自从养成了使用 static_cast 等人的习惯后就进入了列表。而不是 C 风格的转换可以让你在未来省去麻烦。)