“删除”而不是取消分配动态内存

时间:2013-12-01 14:34:51

标签: c++

我正面临一个问题。我写了以下程序:

void main() {

int *ptr;
ptr=new int;


cout<<ptr<<endl;
cout<<&ptr<<endl;


delete ptr;

// ptr = NULL;

cout<<ptr<<endl;
cout<<&ptr<<endl;

}  该计划的输出是:

0x00431810 0x0018FF44 0x00431810 0x0018FF44

“&amp; ptr”肯定是一样的,因为它是ptr自己的地址。但是输出的第1行和第3行清楚地表明,即使在调用“删除”之后,“ptr”也指向相同的存储位置。为什么?如果是这种情况,为什么我们有“删除”而不仅仅依赖NULLING指针。我知道不止一个指针可以指向一个内存位置,但是“删除”是没用的。不是吗?这太令人困惑了。请帮忙。我明天考试。

4 个答案:

答案 0 :(得分:3)

delete ptr不会改变指针的值,但会释放内存。

请注意,释放内存后取消引用ptr会触发undefined behaviour

答案 1 :(得分:1)

当您调用new时,您要求计算机在上分配一些内存并返回指向堆上的位置的指针。

调用delete的做法恰恰相反,它告诉计算机释放指针从堆中指向的内存。这意味着它可以在以后的阶段由您的程序重用。

但是,它不会更改指针的值。最好将指针值设置为NULL。这是因为,指针现在指向的位置可能包含任何内容(计算机可以自由地重复使用此内存)。如果你使用这个指针,它将是未定义会发生什么。

如果您只是将指针更改为NULL,那么所有这一切都会忘记您分配内存的位置。因为C ++不是托管语言,所以它不会检测到你没有任何指向该内存的指针,因此内存将因为你无法访问它而丢失(你不知道它在哪里)而是计算机不能重复使用它(它不知道你已经完成它)。

如果使用C#或Java之类的托管语言,当堆上没有指针时,计算机会释放它(称为垃圾收集),但这会带来性能开销,因此C ++会将其留给程序员。

答案 2 :(得分:1)

指针不知道内存是有效还是已损坏。您可以指向指向任何可以寻址的地址(适合指针)。例如,我的机器指针有8个字节大小,所以我可以做

int main(int argc, char** argv) {

int *ptr;
ptr=new int;

cout<<ptr<<endl;
cout<<&ptr<<endl;

delete ptr;
 //ptr= NULL;

cout<<ptr<<endl;
cout<<&ptr<<endl;

ptr = (int*) 0xffffffff;            
cout<<ptr<<endl;                    //prints 0xffffffff
ptr = (int*) 0xffffffffffffffff;    
cout<<ptr<<endl;                    //prints 0xffffffffffffffff
ptr = (int*) 0xffffffffffffffff1;   
cout<<ptr<<endl;                    //prints 0xfffffffffffffff1  truncated
ptr = (int*) 0xffffffffffffffff321; 
cout<<ptr<<endl;                    //prints 0xfffffffffffff321  truncated
return 0;
}

当你使用new时,它将在堆上的某个地址分配内存并返回指向该地址的指针。

void* operator new (std::size_t size) throw (std::bad_alloc);

指针和内存是两个不同的东西。特别是,您甚至可以手动指定要用于分配的地址(使用放置新语法):

int* ptr = new (0xff1256) int; 
//correct if the memory at 0xff1256 is preallocated
//because placement new only creates object at address
//doesn't allocate memory
  

“ptr”即使在“删除”之后也指向相同的内存位置   叫做。为什么呢?

以同样的方式delete ptr只释放内存,保持指针不变(尽管在调用delete之后立即为指针指定NULL)这是一个很好的做法。它只释放内存,它对你的指针不感兴趣但在地址中释放内存。分配内存或取消分配内存是由操作系统完成的(即内存被标记为已分配)。

答案 3 :(得分:0)

From the documentation,

  

释放由ptr指向的内存块(如果不为null)   先前通过调用operator new分配给它的存储空间   并且呈现指针位置无效

这意味着,delete标记任何其他进程为任何其他目的重用的位置。它从未说过,它会将内存块初始化为任意随机值,以便永远不会再次访问先前存储的数据。因此,即使在调用delete之后,也始终可以提供数据。但是,再一次,这只是Undefined Behavior的可能性之一。多数民众赞成为什么编码,在解除分配后指针NULL