在C++中删除指针

leo*_*pic 80 c++ pointers delete-operator

背景:我试图围绕指针,我们几周前在学校看到它们,今天练习时我遇到了傻瓜?问题,对你来说可能非常简单,但我几乎没有编程经验.

我在SO中看到了很多关于删除指针的问题,但它们似乎都与删除一个类有关,而不是一个"简单"指针(或任何正确的术语),这里是我试图的代码跑:

#include <iostream>;

using namespace std;

int main() {
  int myVar,
      *myPointer;

  myVar = 8;
  myPointer = &myVar;

  cout << "delete-ing pointers " << endl;
  cout << "Memory address: " << myPointer << endl;

  // Seems I can't *just* delete it, as it triggers an error 
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // Error: a.out(14399) malloc: *** error for object 0x7fff61e537f4:
  // pointer being freed was not allocated
  // *** set a breakpoint in malloc_error_break to debug
  // Abort trap: 6

  // Using the new keyword befor deleting it works, but
  // does it really frees up the space? 
  myPointer = new int;
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // myPointer continues to store a memory address.

  // Using NULL before deleting it, seems to work. 
  myPointer = NULL;
  delete myPointer;
  cout << "myPointer: " << myPointer << endl;
  // myPointer returns 0.

}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  1. 为什么第一个案例不起作用?似乎最直接的使用和删除指针?该错误表示内存未分配,但'cout'返回了一个地址.
  2. 在第二个例子中,错误没有被触发,但是做一个myPointer值的cout 仍然返回一个内存地址?
  3. #3真的有用吗?似乎对我有用,指针不再存储地址,这是删除指针的正确方法吗?

很抱歉这个问题很长,想要尽可能清楚,也要重申,我的编程经验很少,所以如果有人能用外行的条款回答这个问题,我们将不胜感激!

Ani*_*han 153

1和2

myVar = 8; //not dynamically allocated. Can't call delete on it.
myPointer = new int; //dynamically allocated, can call delete on it.
Run Code Online (Sandbox Code Playgroud)

第一个变量在堆栈上分配.您只能在使用new运算符动态分配的内存(在堆上)上调用delete .

3.

  myPointer = NULL;
  delete myPointer;
Run Code Online (Sandbox Code Playgroud)

以上什么都没做.你没有释放任何东西,因为指针指向NULL.


不应该做以下事情:

myPointer = new int;
myPointer = NULL; //leaked memory, no pointer to above int
delete myPointer; //no point at all
Run Code Online (Sandbox Code Playgroud)

你把它指向NULL,留下泄漏的内存(你分配的新int).你应该释放你指向的记忆.无法再访问分配的内容new int,因此内存泄漏.


正确的方法:

myPointer = new int;
delete myPointer; //freed memory
myPointer = NULL; //pointed dangling ptr to NULL
Run Code Online (Sandbox Code Playgroud)

更好的方法:

如果您使用的是C++,请不要使用原始指针.使用智能指针,它可以为您处理这些事情,而且开销很小.C++ 11附带了几个.

  • <pedantry>"在堆栈上"是一个实现细节--C++显然避免提及.更正确的术语是"具有自动存储持续时间".(C++ 11,3.7.3)</ pedantry> (12认同)
  • @Tqn那不对.`delete myPointer` deallocates`*myPointer`.那是正确的.但是`myPointer`继续指向已释放的内存位置,不应该使用,因为它是UB.只有在首先它是一个局部变量时,它才会在范围结束后无法访问. (6认同)
  • 谢谢,我选择了你的答案,a)解释出了什么问题,并且b)给出了最佳实践,非常感谢! (4认同)
  • @DarkCthulhu谢谢!(我确实)每天都在学习一些"新东西".(我很俗气!) (2认同)

小智 19

我相信你并没有完全理解指针是如何工作的.
当你有一个指向某个内存的指针时,你必须理解三个不同的东西:
- 指针(内存)有"指向的东西"
- 这个内存地址
- 并非所有指针都需要删除它们的内存:你只有需要删除动态分配的内存(使用的new运算符).

想像:

int *ptr = new int; 
// ptr has the address of the memory.
// at this point, the actual memory doesn't have anything.
*ptr = 8;
// you're assigning the integer 8 into that memory.
delete ptr;
// you are only deleting the memory.
// at this point the pointer still has the same memory address (as you could
//   notice from your 2nd test) but what inside that memory is gone!
Run Code Online (Sandbox Code Playgroud)

当你做到了

ptr = NULL;
// you didn't delete the memory
// you're only saying that this pointer is now pointing to "nowhere".
// the memory that was pointed by this pointer is now lost.
Run Code Online (Sandbox Code Playgroud)

C++允许您尝试delete指向null但实际上并没有执行任何操作的指针,只是不会给出任何错误.

  • 谢谢,这是非常有帮助的,我以为我必须删除所有指针,不知道那只是那些新的,谢谢. (2认同)

use*_*501 12

指针与普通变量类似,因为您不需要删除它们.它们在函数执行结束时和/或程序结束时从内存中删除.

但是,您可以使用指针来分配内存的"块",例如:

int *some_integers = new int[20000]
Run Code Online (Sandbox Code Playgroud)

这将为20000个整数分配内存空间.很有用,因为Stack的大小有限,你可能想要在没有堆栈溢出错误的情况下加入大量的'int'.

无论何时调用new,都应该在程序结束时"删除",否则会出现内存泄漏,并且永远不会返回一些已分配的内存空间供其他程序使用.去做这个:

delete [] some_integers;
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.


fon*_*onZ 7

在C++中有一条规则,对于每一个新的都有删除.

  1. 为什么第一个案例不起作用?似乎最直接的使用和删除指针?该错误表示内存未分配,但'cout'返回了一个地址.

永远不会被称为新的.因此,cout打印的地址是myVar的内存位置的地址,或者在这种情况下分配给myPointer的值.通过写:

myPointer = &myVar;
Run Code Online (Sandbox Code Playgroud)

你说:

myPointer = myVar中数据存储位置的地址

  1. 在第二个例子中,错误没有被触发,但是做一个myPointer值的cout仍然返回一个内存地址?

它返回一个指向已删除的内存位置的地址.因为首先创建指针并将其值分配给myPointer,然后再将其删除,第三步将其打印出来.因此,除非您为myPointer指定其他值,否则将保留已删除的地址.

  1. #3真的有用吗?似乎对我有用,指针不再存储地址,这是删除指针的正确方法吗?

NULL等于0,删除0,因此不删除任何内容.它的逻辑是打印0因为你做了:

myPointer = NULL;
Run Code Online (Sandbox Code Playgroud)

等于:

myPointer = 0;
Run Code Online (Sandbox Code Playgroud)