是否“删除指针”?只是意味着“*指针= 0”?

发布于 2025-01-01 14:49:20 字数 374 浏览 1 评论 0原文

# include <iostream>

int main()  
{  
using std::cout;
int *p= new int;

*p = 10;
cout<<*p<<"\t"<<p<<"\n";
delete p;
cout<<*p<<"\t"<<p<<"\n";

return 0;

}

输出:
10 0x237c010
0 0x237c010

这里删除p后,为什么指针p还保留其值?删除不会释放指针 p 吗?
“释放指针”到底是什么意思?
“删除 p”是否仅仅意味着“*p = 0”?(从输出看来)

# include <iostream>

int main()  
{  
using std::cout;
int *p= new int;

*p = 10;
cout<<*p<<"\t"<<p<<"\n";
delete p;
cout<<*p<<"\t"<<p<<"\n";

return 0;

}

Output:
10 0x237c010
0 0x237c010

Here after deleting p, why the pointer p retains its value? Doesn't delete frees the pointer p?
What exactly is meant by 'freeing the pointer'?
Does 'delete p' simply mean '*p = 0'?(which seems from the output)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

旧时浪漫 2025-01-08 14:49:21

这里删除p后,为什么指针p还保留其值?

这就是语言的设计方式。如果您希望所持有的指针归零,您需要自己将其指定为零。指针 p 是另一块内存,与其指向的分配/对象分开。

delete 不会释放指针 p 吗?

它调用对象的析构函数并将内存返回给系统(如 free)。如果是数组(delete[]),则会调用所有元素的析构函数,然后返回内存。

“释放指针”到底是什么意思?

当您想要从系统中获得一块内存时,您可以分配它(例如使用new)。当您使用完它后,您可以使用相应的释放/删除调用将其返回。这是一种资源,您必须归还。如果你不这样做,你的程序就会泄漏(没有人愿意这样)。

Here after deleting p, why the pointer p retains its value?

It's how the language is designed. If you want the pointer you hold to be zeroed, you'll need to assign it zero yourself. The pointer p is another piece of memory, separate from the allocation/object it points to.

Doesn't delete frees the pointer p?

It calls the destructor the object and returns the memory to the system (like free). If it is an array (delete[]), destructors for all elements will be called, then the memory will be returned.

What exactly is meant by 'freeing the pointer'?

When you want a piece of memory from the system, you allocate it (e.g. using new). When you are finished using it, you return it using the corresponding free/delete call. It's a resource, which you must return. If you do not, your program will leak (and nobody wants that).

梓梦 2025-01-08 14:49:21

为了理解释放内存的含义,您必须首先理解分配内存的含义。以下是一个简化的解释。

记忆是存在的。内存是一大堆你可以访问的东西。但由于它是全球性的,因此您需要某种方法将其分配。某种方式来控制谁可以访问哪些内存片段。管理内存分配的系统之一称为“堆”。

堆拥有一定数量的内存(一些由堆栈拥有,一些由静态数据拥有,但现在没关系)。在程序开始时,堆表示您无权访问堆拥有的内存。

new int 的作用有两个。首先,它进入堆系统并说:“我想要一块适合存储 int 的内存。”它返回一个指向该值的指针:堆的一块,您可以在其中安全地存储和检索一个 int 类型的值。

您现在自豪地拥有一个 int 的内存。堆保证只要遵循其规则,您放入其中的任何内容都将被保留,直到您明确更改它。这是你和全能的堆之间的盟约。

new int 所做的另一件事是使用 int 值初始化堆的该部分。在本例中,它是默认初始化的,因为没有传递任何值(new int(5) 将使用值 5 对其进行初始化)。

从现在开始,法律允许您在这块内存中精确存储一个int。您可以检索存储在那里的int。并且您可以做另一件事:告诉堆您已完成使用该内存。

当您调用delete p时,会发生两件事。首先,p 被取消初始化。同样,因为它是一个 int,所以什么也没有发生。如果这是一个类,则会调用它的析构函数。

但之后,delete 会走到堆中并说:“嘿堆:还记得这个指向你给我的 int 的指针吗?我现在已经完成了。”堆系统可以为所欲为。也许它会清除内存,就像某些堆在调试构建中所做的那样。然而,在发布版本中,内存可能不会被清除。

当然,堆之所以可以为所欲为,是因为在删除该指针的那一刻,您就与堆达成了新的协议。以前,您为 int 请求了一块内存,并且堆满足了要求。您拥有该内存,并且堆保证只要您愿意,它就属于您。你放在那里的东西会保留在那里。

当你玩得很开心之后,你将它返回到堆中。这就是契约的用武之地。当您说 delete p 时,对于 任何 对象 p,您是在说以下内容:

I郑重发誓不再碰这个内存地址!

现在,如果你再次调用new int,堆可能会把那个内存地址还给你。它可能会给你带来不一样的感觉。但您只能在newdelete 之间的 期间访问堆分配的内存。

鉴于此,这意味着什么?

delete p;
cout << *p << "\t" << p << "\n";

用 C++ 术语来说,这称为“未定义行为”。 C++ 规范中有很多内容被声明为“未定义”。当您触发未定义的行为时,任何事情都可能发生! *p 可能是 0。*p 可能是以前的值。执行 *p 可能 使您的程序崩溃。

C++ 规范是您和您的编译器/计算机之间的合同。它说明了您可以做什么,并且说明了系统如何响应。 “未定义的行为”是指当您违反契约、执行 C++ 规范规定您不应该做的事情时发生的情况。到那时,任何事情都可能发生。

当您调用delete p时,您告诉系统您已使用p完成。如果再次使用它,您就对系统撒了谎。因此,系统不再需要遵守任何规则,例如存储您想要存储的值。或者继续跑步。或者不要从你的鼻子里催生恶魔。或者无论如何。

你违反了规则。并且你必须承受后果。

所以不,delete p 并不等同于*p = 0。后者只是意味着“将 0 设置到 p 指向的内存中”。前者的意思是“我已经使用完p指向的内存,我不会再使用它,直到你告诉我我可以。”

In order to understand what freeing memory means, you must first understand what allocating memory means. What follows is a simplified explanation.

There exists memory. Memory is a large blob of stuff that you could access. But since it's global, you need some way to portion it out. Some way to govern who can access which pieces of memory. One of the systems that governs the apportionment of memory is called the "heap".

The heap owns some quantity of memory (some is owned by the stack and some is owned by static data, but nevermind that now). At the beginning of your program, the heap says that you have access to no heap-owned memory.

What new int does is two fold. First, it goes to the heap system and says, "I want a piece of memory suitable to store an int into." It gets back a pointer to exactly that: a piece of the heap, into which you can safely store and retrieve exactly one value of type int.

You are now the proud owner of one int's worth of memory. The heap guarantees that as long as its rules are followed, whatever you put there will be preserved until you explicitly change it. This is the covenant between you and the almighty heap.

The other thing new int does is initialize that piece of the heap with an int value. In this case, it is default initialized, because no value was passed (new int(5) would initialize it with the value 5).

From this point forward, you are legally allowed to store exactly one int in this piece of memory. You are allowed to retrieve the int stored there. And you're allowed to do one other thing: tell the heap that you are finished using that memory.

When you call delete p, two things happen. First, p is deinitialized. Again, because it is an int, nothing happens. If this were a class, its destructor would be called.

But after that, delete goes out to the heap and says, "Hey heap: remember this pointer to an int you gave me? I'm done with it now." The heap system can do whatever it wants. Maybe it will clear the memory, as some heaps do in debug-builds. In release builds however, the memory may not be cleared.

Of course, the reason why the heap can do whatever it wants is because, the moment you delete that pointer, you enter into a new agreement with the heap. Previously, you asked for a piece of memory for an int, and the heap obliged. You owned that memory, and the heap guaranteed that it was yours for as long as you wanted. Stuff you put there would remain there.

After you had your fun, you returned it to the heap. And here's where the contract comes in. When you say delete p, for any object p, you are saying the following:

I solemnly swear not to touch this memory address again!

Now, the heap might give that memory address back to you if you call new int again. It might give you a different one. But you only have access to memory allocated by the heap during the time between new and delete.

Given this, what does this mean?

delete p;
cout << *p << "\t" << p << "\n";

In C++ parlance, this is called "undefined behavior". The C++ specification has a lot of things that are stated to be "undefined". When you trigger undefined behavior anything can happen! *p could be 0. *p could be the value it used to be. Doing *p could crash your program.

The C++ specification is a contract between you and your compiler/computer. It says what you can do, and it says how the system responds. "Undefined behavior" is what happens when you break the contract, when you do something the C++ specification says you aren't supposed to. At that point, anything can happen.

When you called delete p, you told the system that you were finished using p. By using it again, you were lying to the system. And therefore, the system no longer has to abide by any rules, like storing the values you want to store. Or continuing to run. Or not spawning demons from your nose. Or whatever.

You broke the rules. And you must suffer the consequences.

So no, delete p is not the equivalent of *p = 0. The latter simply means "set 0 into the memory pointed to by p." The former means "I'm finished using the memory pointed to by p, and I won't use it again until you tell me I can."

姜生凉生 2025-01-08 14:49:21

这里删除p后,为什么指针p还保留其值?删除不会释放指针 p 吗?

它释放指针指向的内存(在调用任何适当的析构函数之后)。指针本身的值没有改变。

“释放指针”到底是什么意思?

如上所述 - 这意味着释放指针指向的内存。

“删除 p”只是意味着“*p = 0”吗?(从输出看来)

否。系统不会向释放的内存写入任何内容,如果确实写入不必写 0 的东西。但是,系统通常必须以某种方式管理该内存,并且这实际上可能会写入指针指向的内存区域。此外,刚刚释放的内存可以分配给其他东西(在多线程应用程序中,这可能在删除操作返回之前发生)。该内存块的新所有者当然可以向该内存写入他们想要的任何内容。

指向已释放内存块的指针通常称为“悬空”指针。取消引用悬空指针(用于读取或写入)是错误的。有时您会看到代码在删除指针后立即将 NULL0 分配给指针,有时会使用同时删除和清除指针的宏或函数模板。请注意,这不会修复所有悬空指针的错误,因为其他指针可能已设置为指向内存块。

处理此类问题的现代方法是完全避免使用原始指针,而使用智能指针,例如 shared_ptrunique_ptr

Here after deleting p, why the pointer p retains its value? Doesn't delete frees the pointer p?

It frees the memory the pointer points to (after calling any appropriate destructor). The value of the pointer itself is unchanged.

What exactly is meant by 'freeing the pointer'?

As above - it means freeing the memory the pointer points to.

Does 'delete p' simply mean '*p = 0'?(which seems from the output)

No. The system doesn't have to write anything to the memory that's freed, and if it does write something it doesn't have to write 0. However, the system does generally have to manage that memory in some way, and that might actually write to the area of memory that the pointer was pointing to. Also, the just-freed memory can be allocated to something else (and in a multi-threaded application, that could happen before the delete operation even returns). The new owner of that memory block can of course write whatever they want to that memory.

A pointer that is pointing to a freed block of memory is often known as a 'dangling' pointer. It is an error to dereference a dangling pointer (for read or write). You will sometimes see code immediately assign a NULL or 0 to a pointer immediately after deleting the pointer, sometimes using a macro or function template that both deletes and clears the pointer. Note that this won't fix all bugs with dangling pointers, since other pointers may have been set to point to the memory block.

The modern method of dealing with these kinds of problems is to avoid using raw pointers altogether in favor of using smart pointers such as shared_ptr or unique_ptr.

恰似旧人归 2025-01-08 14:49:21

delete p 只是释放在调用 new 运算符期间分配的内存。它不会更改指针的值或已释放内存的内容。

delete p simply frees the memory allocated during a call to the new operator. It does not change the value of the pointer or the content of the deallocated memory.

尽揽少女心 2025-01-08 14:49:21

(请注意,以下内容并不是它实际的工作原理,因此请对此持保留态度。)

在 new 的实现内部,当您说“int *p= new int;”时,它会保留所有可用内存的列表。它从可用内存列表中删除了一个 int 大小的块并将其提供给您。当你运行“delete p;”时它被放回到可用内存列表中。如果您的程序调用 new 30 次而根本没有调用 delete,您将从 new 中获得 30 个不同 int 大小的块。如果你连续调用 new 然后删除 30 次,你可能(但不一定)得到相同的 int 大小的块。这是因为您在调用删除时说过您不再使用它,因此 new 可以自由地重用它。

太长了;删除会通知新的这部分内存再次可用,它不会触及您的变量。

(Note the following isn't how it actually works so take it with a grain of salt.)

Inside the implementation of new it keeps a list of all available memory when you said "int *p= new int;" it cut a int sized block off of its list of available memory and gave it to you. When you run "delete p;" it gets put back in the list of available memory. If your program called new 30 times without calling delete at all you would get 30 different int sized chunks from new. If you called new then delete 30 times in a row you might (but not necessarily) get the same int sized block. This is because you said you weren't using it any more when you called delete and so new was free to reuse it.

TLDR; Delete notifies new that this section of memory is available again it doesn't touch your variable.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文