【问题标题】:Multiple pointers to an object defined in the heap指向堆中定义的对象的多个指针
【发布时间】:2013-12-01 00:25:50
【问题描述】:

假设我有一个指向 Student 对象的临时指针(不管 Student 的定义是什么 - 假设它不包含指针数据成员),我使用如下:

int main(){
Student *temp;
Student *s1 = new s1("John", 21);
Student *s2 = new s2("Jane", 23);
//do whatever;
temp = s1;
s1 = s2;
s2 = temp;

delete s1;
delete s2;

return 0;
}

由于我将new 用于s1s2,因此我知道对象是在堆中创建的,因此我需要使用delete 运算符来摆脱它们。我的问题是 - 我需要“删除临时”吗?如果不是,为什么?如何管理“临时”内存?有人能解释一下内存管理器如何处理这个指针,当它超出范围时会发生什么?

【问题讨论】:

  • 无关:delete s1, s2 是什么?
  • 1. temp 指向什么对象? 2. 您是否已经通过不同的指针删除了该对象?回答这两个,你应该知道你的问题的答案。
  • @0x499602D2 :已修复,谢谢。

标签: c++ pointers


【解决方案1】:

首先,你不能删除2个具有相同delete的对象,所以这行不通:

delete s1, s2;

这只是删除了 s1 指向的对象,对s2 没有任何作用(参见:comma operator)。将其更改为 2 个单独的语句。

除此之外,您不必在temp 上调用delete,因为它指向的对象(与s2 指向的对象相同)已经被销毁并通过调用释放:

delete s2;

但是,您可以调用delete temp; 而不是 delete s2;,因为它们都指向同一个对象。你甚至可以这样做:

delete temp;
temp = s1;
delete temp;

delete 通过指向它们的指针作用于使用new 分配的对象。你在哪个指针上调用 delete 并不重要。仅在调用指针时将哪个地址存储在指针中很重要。并且该地址必须是之前由new 返回但尚未删除的地址。

至于这个:

有人能解释一下内存管理器如何处理这个指针吗? 当它超出范围时会发生什么?

当指针超出范围时什么都不会发生。至少,像intchar 这样的常规变量不会发生任何事情,也许堆栈指针会被移动,但这是一个实现细节。

【讨论】:

  • @srihari 特别注意结尾句中的 "instead of" 字样。这是您的问题的基础。
【解决方案2】:

您不必删除temp,因为这只是指针的副本,因为您正在删除实际分配的缓冲区。这是一个auto 变量,一旦超出范围就会被删除。

如果您的类Student 覆盖assignment 运算符以创建copy,那么您可以显式地delete 变量,或者在函数返回后将其删除。

【讨论】:

  • 我不太明白第二部分——你的意思是做一个深拷贝吗?如果是这样,temp 不会指向堆中s1 指向的对象的副本吗?在那种情况下,我不必显式调用delete temp 吗?函数返回时如何删除?
  • @Srihari.. 请参考这个链接,我觉得这对调用 delete stackoverflow.com/questions/10081429/… 的主题非常有用。当然,显式调用delete 绝对是一个好习惯,但这更多归功于C 程序员而不是C++ 程序员。
【解决方案3】:

我想我明白了 - temp 只是堆栈上的一个整数,一旦超出范围就会由内存管理器处理,就像任何堆栈变量一样。

temps1 现在指向同一个内存位置:因此,删除 s1 会处理 temp 指向的对象。在这个阶段不会因为temp 导致内存泄漏。但是,如果我尝试访问temp,在delete s1; 语句之后,我的程序可能会崩溃。

【讨论】:

  • 注意:temp 不是“堆栈上的整数”。它是一个指针,它的表示是依赖于实现的,你不一定知道。您的其余答案完全准确,听起来您理解。 +1(并考虑对其他有用的答案进行投票)。
  • @WhozCraig :我的理解是指针只是用于存储内存地址,而这些地址又只是十六进制表示的整数......如何 else 存储指针?如果它不总是存储为整数,我们是否需要在进行指针运算之前知道指针是如何实现的(例如,ptr++)? (+1 提出这个问题,我不知道指针并不总是被实现为整数。:)
  • “地址”这个词是依赖于实现的。重点是您不必知道“它”实际上是什么,只要您遵守标准规则即可。有一些 惊人的 平台通过实现指针和地址来做一些事情,这会让大多数人感到困惑(AS/400 就是其中之一)。
  • 还应该注意的是,您习惯看到的十六进制表示正是您的ostreamprintf 实现者选择显示它们的方式。它与它们的实际存储无关,它和其他所有东西一样都是二进制的。
猜你喜欢
  • 2013-03-14
  • 1970-01-01
  • 1970-01-01
  • 2023-02-09
  • 2017-12-06
  • 2012-02-05
  • 2011-05-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多