【问题标题】:C++ delete a pointer (free memory)C++ 删除指针(释放内存)
【发布时间】:2017-03-01 06:08:37
【问题描述】:

考虑以下代码:

int a = 10;
int * b = &a;
int * c = b;
delete b; // equivalent to delete c;

我在最后一行的理解是否正确,delete bdelete c 是等价的,并且两者都会释放保存 a 的内存空间,因此 a 不再可访问?

【问题讨论】:

  • a 尚未动态分配,因此在其上使用 delete 会导致未定义的行为。 :(
  • a 是在栈上创建的,不需要删除它。
  • 如果我们忽略堆栈对象的delete...如果b 指向new 分配的对象,是的,你是正确的deleteing c 或@ 987654333@ 等价:两者都指向同一个 deleted 对象
  • @AndrewHenle 但是甚至不需要 sigsegv。
  • 您不会在 C++ 中删除指针。 您会删除使用 new 分配的对象。

标签: c++ pointers memory-management


【解决方案1】:

您的程序的行为是未定义。您可以在指向使用new 分配的内存的指针上使用delete。如果你写了

int* b = new int;
*b = 10;
int* c = b;

那么你可以或者delete b;或者delete c;来释放你的记忆。不要尝试在delete 调用之后取消引用 bc,这样做的行为也是未定义

【讨论】:

  • 这也是原始指针如此危险的原因。没有办法知道某个指针指向的动态分配的内存是否被另一个指向同一内存的指针删除。并试图通过取消引用来“检查”会导致未定义的行为。
  • @GillBates 这就是为什么原始 owning 指针是危险的。非拥有指针很好。
  • @NathanOliver 如果您不使用智能指针并且您 new 某些东西,那么您将拥有自己的指针。我们还没有在这里讨论智能指针,所以当谈到原始指针的危险时,我不会提出它。
  • 我不这么认为。为了有一个弱指针,你需要一个共享指针,所以现在你有原子引用计数。如果我只想从容器中返回一个元素,并且如果它不存在我想返回null,那么原始指针就可以了。智能指针已经存在,但智能指针无处不在,恕我直言。
  • 在不存在的情况下,如果它绝对必须是一个指针,我更愿意返回类似std::optional<gsl::not_null<T*>> 的东西。这实现了相同的目标,但使界面很多更具表现力。用户忘记或忽略“空”返回值的可能性将大大降低。
【解决方案2】:

令人困惑的部分是你的问题的答案

最后一行我理解正确吗,delete b和delete c是等价的”

是的,它们是等价的,并且这里其他地方都提到了这两个 UB。

【讨论】:

  • 嗯,这似乎是一个哲学问题的开端。编译器不需要以相同的方式处理delete bdelete c,因为对于看到它们应该做什么完全没有要求。因此,要确定它们是否“等价”,我们必须确定“等价”的含义。 . .
【解决方案3】:

如果bc 指向同一个内存,那么删除它们中的任何一个都会释放内存,因此假设是正确的。 a 在这种情况下变得不可访问是不正确的,因为您没有指向动态分配的内存,并且您只能在使用 new/new[] 创建的东西上调用 delete/delete[]。尝试 delete/delete[] 未分配 new/new[] 的指针是未定义的行为,通常会以分段错误结束。

【讨论】:

  • @TheGreatDuck 我说的是一般,并非总是如此。首先,它是未定义的行为。无论最终发生什么都无关紧要。
  • @TheGreatDuck 那是个稻草人。 UB 并不意味着该代码将格式化您的硬盘。
  • @TheGreatDuck 我不喜欢例外。相反,当我需要拥有指针时,我更喜欢封装并使用智能指针。然后就不用担心,也不会产生异常开销,除非抛出 new ,但此时确实无事可做。
  • @TheGreatDuck 能不能算GC,是的。是吗,看情况。如果您使用std::unique_ptr,它不会比使用原始newdelete 更多开销,但除非您尝试破坏它,否则它是100% 安全的。 shared_ptr 有点像 GC,因为它有一个引用计数,但它是细粒度的,因为它只适用于指针,而不适用于代码中的其他任何内容。
【解决方案4】:

你不应该对分配在堆栈上的变量使用 delete, 删除是新的对应物。 因此,当没有使用 new/alloc 时,不需要删除/释放,一旦你超出了代码的“范围”(在这种情况下是程序本身),所有内存都被认为是可用的。

【讨论】:

  • 不要说“堆栈”——它不是一个语言概念。请改用 C++ 标准定义的术语“自动存储持续时间”。
  • 另外,您从错误的角度接近它。对具有静态存储持续时间的变量(例如全局变量)使用 delete 也是错误的。您可以通过说明您应该做什么来更准确:仅对new 返回的指针使用delete。甚至new[]返回的那些也没有。
猜你喜欢
  • 2016-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-28
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多