我正在阅读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_ownership
。 container_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)浮动引用的概念是一个糟糕的设计决策。这是真的吗?
答案 0 :(得分:1)
StackOverflow实际上不是与GObject和G *平台的API设计人员讨论这个问题的好方法。您可能想要在gtk-devel邮件列表上询问。
是的,浮动参考只是进行所有权转移的一种奇特方式。
“移动所有权”API方法的问题在于指针所有权没有明确定义的类型语义。你根本就不知道 - 除非你事先用container_add_with_ownership_transfer()
笨拙地命名你的API。此外,这意味着某些API可以使用所有权转移,但无法通过类型检查发现它。这对于语言绑定来说尤其至关重要,因为他们需要知道所有权转移规则。
最近,GObject为内省目的获得了额外的注释,但当然修改API和输入系统已经为时已晚。
答案 1 :(得分:0)
您的解决方案的问题在于您必须创建两个函数:
考虑您不想移动所有权的情况。在这种情况下,您有两个选择:
container_add_child_move_ownership(container, g_object_ref(child))
container_add_child(container, child)
使用浮动引用,您只有一个函数适用于这两种情况。
<块引用>就我个人而言,是的,这是糟糕的设计。您的移动所有权解决方案比浮动引用的解决方案更清晰,即使您必须创建两个函数(但我会为移动函数取短名称,如 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() 返回完整引用。