2012-11-04 59 views
51

上下文:我试图围绕着指针,几周前我们在学校看到了他们,而在今天练习时,我遇到了一个愚蠢的问题?问题,它对你来说可能是非常直接的,但我几乎没有任何编程经验。在C++中删除一个指针

我看过很多关于删除指针的问题,但它们似乎都与删除类而不是“简单”指针(或任何适当的术语可能)有关,下面是代码I “M试图运行:

#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. 

} 

所以我的问题是:

  1. 为什么不会第一种情况的工作?看起来最直接的用法是使用和删除一个指针?错误表示内存未分配,但'cout'返回了一个地址。
  2. 在第二个示例中,错误未被触发,但是执行myPointer 仍然的值的返回内存地址?
  3. 3号真的有用吗?似乎工作给我,指针不再存储地址,这是删除指针的正确方法?

对不起,我想让这个尽可能的清晰,也要重申一下,我没有什么编程经验,所以如果有人能够用通俗的话来回答这个问题,那将不胜感激!

+11

你没有看到第一个例子的原因是因为它是错误的。只有'删除'你'新'。指针在删除它之后将其自身设置为NULL也不是必需的。如果您想在那里安全,请使用智能指针,这会为您释放内存,并在您尝试访问内存时发生错误,因为这些内存不包含内容。 – chris

+0

嗯好吧,我不确定什么是智能指针,但我会研究它,谢谢! – leopic

+1

简而言之,他们按照我所描述的来做。为了保持新的东西,你可以调用'reset'并且释放旧的。要免费更换,请致电'release'。当它超出范围时,它就会被销毁,并且可以根据它的类型释放内存。 'std :: unique_ptr'仅适用于一个所有者。当最后一个拥有者停止拥有资源时,'std :: shared_ptr'释放它。他们也是例外安全的。如果您使用一个资源分配资源,然后遇到异常,资源将被正确释放。 – chris

回答

106

myVar = 8; //not dynamically allocated. Can't call delete on it. 
myPointer = new int; //dynamically allocated, can call delete on it. 

第一可变被分配在堆栈中。您只能在您使用new运算符动态分配的内存上调用delete(在堆上)。

myPointer = NULL; 
    delete myPointer; 

上面做了所有什么。你没有释放任何东西,因为指针指向NULL。


下不应该做的:

myPointer = new int; 
myPointer = NULL; //leaked memory, no pointer to above int 
delete myPointer; //no point at all 

您在NULL指出它,留下泄漏的内存(新的诠释你分配)。 你应该释放你指向的内存。没有办法再访问分配的new int,因此内存泄漏。


正确的方法:

myPointer = new int; 
delete myPointer; //freed memory 
myPointer = NULL; //pointed dangling ptr to NULL 

更好的方法:

如果您使用C++,使用原始指针。代之以使用smart pointers,它可以很少的开销为您处理这些事情。 C++ 11自带several

+9

“在堆栈上”是一个实现细节 - C++明显避免提及的细节。更正确的术语是“具有自动存储持续时间”。 (C++ 11,3.7.3) cHao

+4

谢谢你,我选择了你的答案:a)解释什么是错的,b)给出最佳实践,非常感谢! – leopic

+0

我想补充一点,不管这篇文章多大年纪(为了google的缘故),'delete myPointer'释放'* myPointer','myPointer'不再指向任何东西。它将在范围的最后被销毁。 – Tqn

7

有一个在C++的规则,对每个有一个删除

  1. 为什么不会第一种情况的工作?看起来最直接的用法是使用和删除一个指针?错误表示内存未分配,但'cout'返回了一个地址。

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

myPointer = &myVar; 

你说:

myPointer =在myVar的数据被存储在那里的地址

  • 论第二个示例错误未被触发,但是执行myPointer值的cout仍然返回内存地址?
  • 它返回一个指向已被删除的内存位置的地址。因为首先创建指针并将其值分配给myPointer,然后将其删除,然后将其打印出来。因此,除非您为myPointer指定另一个值,否则删除的地址将保留。

    1. 3号真的有效吗?似乎工作给我,指针不再存储地址,这是删除指针的正确方法?

    NULL等于0,您删除0,因此您什么都不删除。而且,那是因为你没有它打印0逻辑:这等于

    myPointer = NULL; 
    

    myPointer = 0; 
    
    4
    1. 您正试图删除在栈上分配的变量。你不能这样做
    2. 删除指针实际上并不会破坏指针,只是将占用的内存回送给操作系统。您可以访问它,直到内存被用于另一个变量或以其他方式操作。所以最好在删除后将指针设置为NULL(0)。
    3. 删除空指针不会删除任何内容。
    10

    指针与正常变量相似,因为您不需要删除它们。它们在函数执行结束时和/或程序结束时从内存中移除。

    但是,您可以使用指针来分配的内存“块”,例如像这样:

    int *some_integers = new int[20000] 
    

    这将分配内存空间,20000点的整数。很有用,因为堆栈的大小有限,您可能想要在不发生堆栈溢出错误的情况下大量加载“ints”。

    每当你调用new时,你应该在你的程序结束时'删除',否则你会得到内存泄漏,并且一些分配的内存空间永远不会返回供其他程序使用。要做到这一点:

    delete [] some_integers; 
    

    希望有所帮助。

    +1

    我想补充一点,分配的内存将返回给其他程序使用,但只有在您的程序执行完毕后。 – sk4l

    1
    int value, *ptr; 
    
    value = 8; 
    ptr = &value; 
    // ptr points to value, which lives on a stack frame. 
    // you are not responsible for managing its lifetime. 
    
    ptr = new int; 
    delete ptr; 
    // yes this is the normal way to manage the lifetime of 
    // dynamically allocated memory, you new'ed it, you delete it. 
    
    ptr = nullptr; 
    delete ptr; 
    // this is illogical, essentially you are saying delete nothing. 
    
    +1

    另外,请参阅有关指针上的堆栈帧http://www.youtube.com/watch?v=bjObm0hxIYY和http://www.youtube.com/watch?v=Rxvv9krECNw的讲座。 –

    12

    我相信你并不完全理解指针是如何工作的。
    当你有一个指针指向一些内存有三种不同的东西,你必须明白:
    - 有“什么是尖”的指针(内存)
    - 这个内存地址
    - 不是所有的指针需要删除其内存:您只需删除动态分配的内存(使用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! 
    

    当你做

    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. 
    

    C++允许您尝试delete指向null一个指针,但它实际上并没有做任何事情,只是不给任何错误。

    +1

    谢谢,这是超级有用的,我想我有删除所有的指针,不知道这只是为new'd,谢谢。 – leopic