浮点引用GObject的替代方法

时间:2017-03-08 09:25:36

标签: memory-management garbage-collection gobject

我正在阅读lecture on GTK+ memory management章节"对象从GInitiallyUnown ed。降序"引入了浮动引用的概念,因此我们可以编写代码

container = create_container();
container_add_child(container, create_child());

而不是

Child *child;
container = create_container();
child = create_child();
container_add_child(container, child);
g_object_unref(child);

我立即意识到同样可以实现如下。有一个函数container_add_child_move_ownershipcontainer_add_child是多余的。假设container_add_child_move_ownership(container, child)将所有权从调用者移至container,因此container_add_child_move_ownership不会更改引用计数。因此,以下示例是正确的。

void f(Container *container) {
    container_add_child_move_ownership(container, create_child());
}

要么0)我的解决方案有一个我看不到的缺陷,或者1)浮动引用的概念是一个糟糕的设计决策。这是真的吗?

2 个答案:

答案 0 :(得分:1)

StackOverflow实际上不是与GObject和G *平台的API设计人员讨论这个问题的好方法。您可能想要在gtk-devel邮件列表上询问。

是的,浮动参考只是进行所有权转移的一种奇特方式。

“移动所有权”API方法的问题在于指针所有权没有明确定义的类型语义。你根本就不知道 - 除非你事先用container_add_with_ownership_transfer()笨拙地命名你的API。此外,这意味着某些API可以使用所有权转移,但无法通过类型检查发现它。这对于语言绑定来说尤其至关重要,因为他们需要知道所有权转移规则。

最近,GObject为内省目的获得了额外的注释,但当然修改API和输入系统已经为时已晚。

答案 1 :(得分:0)

<块引用>
  1. 我的解决方案有一个我看不到的缺陷

您的解决方案的问题在于您必须创建两个函数:

  • container_add_child。
  • container_add_child_move_ownership。

考虑您不想移动所有权的情况。在这种情况下,您有两个选择:

  1. 在将对象移入函数之前增加对象的引用计数:

container_add_child_move_ownership(container, g_object_ref(child))

  1. 添加另一个不移动所有权的函数:

container_add_child(container, child)

使用浮动引用,您只有一个函数适用于这两种情况。

<块引用>
  1. 浮动引用的概念是一个糟糕的设计决策。

就我个人而言,是的,这是糟糕的设计。您的移动所有权解决方案比浮动引用的解决方案更清晰,即使您必须创建两个函数(但我会为移动函数取短名称,如 container_add_child_mv)。

对于浮动引用,您必须考虑 which function to use g_object_ref_sink 或仅 g_object_ref。对于浮动引用,您必须handle potentially floating parameters carefully

甚至 GLib 文档也有关于浮动引用的 note

注意:浮动引用是一个 C 方便的 API,不应在现代 GObject 代码中使用。特别是语言绑定发现这个概念非常有问题,因为浮动引用无法通过注释识别,浮动引用行为也没有偏差,例如继承自 GInitiallyUnowned 的类型仍然从 g_object_new() 返回完整引用。