https://developer.gnome.org/glib/unstable/glib-GVariant.html#g-variant-ref-sink
我已经阅读了上面的glib手册,上面写着:" GVariant
使用浮动引用计数系统。名称以g_variant_new_
开头的所有函数都返回浮动引用。"但浮动引用计数的实际描述在哪里?我无法找到它的全面描述。
特别是我想了解什么时候需要引用一个变体,何时不需要。例如:
GVariant *a_v = g_variant_new_boolean(TRUE);
GVariant *another_v = g_variant_new("v", a_v);
a_v
,因为它被第二个g_variant_new
消耗。这是对的吗?another_v
(假设another_v
从那时起没有传递给其他任何内容?)答案 0 :(得分:8)
GObject参考手册中有一个关于floating references的部分,其中详细介绍了一些内容。浮动引用可能看起来有点模糊,但它们对C非常有用,因此花几分钟时间来真正理解它们是一个好主意。
我将假设您了解引用计数的工作原理 - 如果没有大量文档,请花几分钟时间阅读。
首先,让我们看看如果g_variant_new_boolean
返回常规引用,您的示例会发生什么。当您第一次获得该值时,引用计数将为1.当您将其传递给g_variant_new
时,g_variant_new
会将引用计数增加到2.在某些时候,我假设您将处置{{ 1}},此时another_v
的引用计数将降为1 ......但请记住,在引用计数达到0之前,内存不会被释放。
为了解决这个问题,您有两种选择。第一个是让a_v
窃取来电者的参考,这基本上是一个解决方案。当您致电g_variant_new
(或任何类似的功能)时,您会放弃您的参考,因此将来每次您想要将其传递给其他人时,您需要手动引用g_variant_new
。
另一种选择是在完成后手动取消它。它不是世界末日,但很容易忘记做错或错误(比如忘记在错误路径中取消它)。
GVariant所做的是返回“浮动”参考。最简单的思考方式(恕我直言)是第一次调用它a_v
它并没有真正做任何事情 - 它只是“沉没”浮动引用。引用计数从1到1. 对g_variant_ref
的后续调用会增加引用计数。
现在让我们看看你的例子实际发生了什么。 g_variant_ref
返回浮动引用。然后,您将其传递给g_variant_new_boolean
,g_variant_new
会调用g_variant_ref
,这会吸收浮动引用。引用计数现在为1,当another_v
的引用计数达到0 a_v
时,引用计数将递减,在这种情况下将达到0并且所有内容都将被释放。您无需致电g_variant_unref
。
关于浮动引用的很酷的部分是这样的事情:
GVariant *a_v = g_variant_new_boolean(TRUE);
GVariant *another_v = g_variant_new("v", a_v);
GVariant *yet_another_v = g_variant_new("v", a_v);
当g_variant_new
被调用时,第二次a_v
的引用计数将再次递增(至2)。在第二次将g_variant_ref
传递给a_v
之前无需调用g_variant_new
- 第一次调用看起来就像第一次调用一样,并且一致性是API中非常好的功能。
此时它可能很明显,但是,您需要在g_variant_unref
上调用another_v
(在最后一个示例中,yet_another_v
)。
答案 1 :(得分:0)
参考计数系统在GObject的手册中有解释,特别是在Object Memory Management部分。
何时使用它可能取决于您的应用程序(变量的所有权如何起作用)。
这个想法类似于i-node在处理文件时在Unix / Linux中的工作方式。文件是一个对象,位于存储中的特定块中。每当您为该文件创建符号链接时,该文件由一个额外文件拥有(引用计数增加)。每当删除符号链接时,引用计数都会减少。当没有任何东西拥有该对象时,它就可以被销毁(或者可以将空间返回给系统)。
如果您销毁某个对象,并且没有任何内容链接该对象,则无法再使用它。如果您的对象可能有多个所有者,那么您可能希望使用引用计数,因此当其中一个所有者删除一个计数器时,该对象不会被销毁...直到最后一个所有者销毁它。