什么使 C++ 中的堆分配对象 "referenced"?
What makes a heap allocated object "referenced" in C++?
在 C++ 中,什么决定了要引用堆分配的对象? Mark Allen Weiss 在他的《Data Structures and Algorithm Analysis in C++》一书中写到“当一个对象被new分配时不再被引用,delete操作必须应用于该对象(通过指针)”我觉得这句话有点令人困惑,我所理解的是指针持有对内存地址的引用,但是表示该地址的对象如何被其他东西引用?当其他东西不再引用它时,我必须调用 delete?
我不会太痴迷于那里的语言的精确选择。他想说的是,如果您在堆上分配了一个对象,那么您有责任在使用完后取消分配它。否则会一直有效,浪费内存。
您可以完全处理一个对象,即使它仍然被引用。确切地说,何时删除对该对象的所有引用以及何时取消分配它取决于您。重点很简单,你肯定不想在你取消分配后尝试使用它,你也不希望在很长一段时间内无法取消分配大量对象并浪费内存。
幸运的是,在现代 C++ 中,您有许多工具可以使这变得更加容易,包括移动语义、unique_ptr
等等。
how is the object that represents this address referenced by something
else?
这意味着您程序中的其他内容持有指向堆分配对象的内存位置的指针(或引用,对于我们的目的而言,这相当于同一事物)。
And when that something else is no longer referencing it, I have to
call delete?
好吧,您 不必 -- 另一种方法是忘记该对象,根本不删除它,这被称为内存泄漏。唯一的问题是,如果您不删除该对象,则该对象占用的 RAM(和任何其他资源)将永远不会被释放(至少在您的程序退出之前不会),并且如果您不断泄漏对象,最终您的计算机将 运行 内存不足并逐渐停止。所以对于生命周期很短的程序,马虎一点,不删除不再被引用的对象可能是可以的,但一般来说,最好自己清理一下。
Moreover, could you please tell me about sources I can read that would
clarify the usage of memory in C++?
任何一本像样的 C++ 书籍都应该有一节介绍它;一般来说,最好的做法是在处理堆分配对象时使用智能指针(如 std::unique_ptr
或 std::shared_ptr
)而不是普通的旧 C 风格指针。这种方式更不容易出错,因为你永远不必弄清楚何时是调用 delete
的正确时间,因为指针-class 会在正确的时间自动为你调用 delete。
只是为了说明
int* a = new int;
int* b = a;
看起来像这样:
+---
| a | --\
+---+ \ +-----------------------+
>--> | heap allocated memory |
+---+ / +-----------------------+
| b | --/
+---+
两个指针 a
和 b
都指向完全相同的内存。
如果您在此之后 delete a
,则 a
和 b
均无效。
这本书有误。没有关于“引用”和delete
的规则。规则是当您不再需要 delete
new
分配的对象时 .
当书中说该对象“不再被引用”时,实际上意味着不再需要该对象。您必须至少有一个对该对象的引用,否则您甚至不能 delete
它!
“引用”意味着您的程序知道对象的地址,因为它存储在变量中。
在 C++ 中,什么决定了要引用堆分配的对象? Mark Allen Weiss 在他的《Data Structures and Algorithm Analysis in C++》一书中写到“当一个对象被new分配时不再被引用,delete操作必须应用于该对象(通过指针)”我觉得这句话有点令人困惑,我所理解的是指针持有对内存地址的引用,但是表示该地址的对象如何被其他东西引用?当其他东西不再引用它时,我必须调用 delete?
我不会太痴迷于那里的语言的精确选择。他想说的是,如果您在堆上分配了一个对象,那么您有责任在使用完后取消分配它。否则会一直有效,浪费内存。
您可以完全处理一个对象,即使它仍然被引用。确切地说,何时删除对该对象的所有引用以及何时取消分配它取决于您。重点很简单,你肯定不想在你取消分配后尝试使用它,你也不希望在很长一段时间内无法取消分配大量对象并浪费内存。
幸运的是,在现代 C++ 中,您有许多工具可以使这变得更加容易,包括移动语义、unique_ptr
等等。
how is the object that represents this address referenced by something else?
这意味着您程序中的其他内容持有指向堆分配对象的内存位置的指针(或引用,对于我们的目的而言,这相当于同一事物)。
And when that something else is no longer referencing it, I have to call delete?
好吧,您 不必 -- 另一种方法是忘记该对象,根本不删除它,这被称为内存泄漏。唯一的问题是,如果您不删除该对象,则该对象占用的 RAM(和任何其他资源)将永远不会被释放(至少在您的程序退出之前不会),并且如果您不断泄漏对象,最终您的计算机将 运行 内存不足并逐渐停止。所以对于生命周期很短的程序,马虎一点,不删除不再被引用的对象可能是可以的,但一般来说,最好自己清理一下。
Moreover, could you please tell me about sources I can read that would clarify the usage of memory in C++?
任何一本像样的 C++ 书籍都应该有一节介绍它;一般来说,最好的做法是在处理堆分配对象时使用智能指针(如 std::unique_ptr
或 std::shared_ptr
)而不是普通的旧 C 风格指针。这种方式更不容易出错,因为你永远不必弄清楚何时是调用 delete
的正确时间,因为指针-class 会在正确的时间自动为你调用 delete。
只是为了说明
int* a = new int;
int* b = a;
看起来像这样:
+--- | a | --\ +---+ \ +-----------------------+ >--> | heap allocated memory | +---+ / +-----------------------+ | b | --/ +---+
两个指针 a
和 b
都指向完全相同的内存。
如果您在此之后 delete a
,则 a
和 b
均无效。
这本书有误。没有关于“引用”和delete
的规则。规则是当您不再需要 delete
new
分配的对象时 .
当书中说该对象“不再被引用”时,实际上意味着不再需要该对象。您必须至少有一个对该对象的引用,否则您甚至不能 delete
它!
“引用”意味着您的程序知道对象的地址,因为它存储在变量中。