Memory management 对GObject的浮动引用的替代方法

Memory management 对GObject的浮动引用的替代方法,memory-management,garbage-collection,gobject,Memory Management,Garbage Collection,Gobject,我正在读一章,物体从吉尼塔里降下来。为了编写代码,引入了浮动引用的概念 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 = 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);
我立即意识到,同样的事情也可以通过以下方式实现。有一个函数容器(添加)(子项)(移动)(所有权)。容器添加子项是多余的。假定容器\u添加\u子对象\u移动\u所有者容器,子对象将所有权从调用方移动到容器,因此容器\u添加\u子对象\u移动\u所有权不会更改引用计数。因此,以下示例是正确的

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

要么0我的解决方案有我看不到的缺陷,要么1浮动引用的概念是一个错误的设计决策。哪一个是真的?

StackOverflow并不是与GObject和G*平台的API设计师讨论这个问题的好方法;你可能想在邮件列表上询问

是的,浮动引用只是进行所有权转移的一种奇特方式

移动所有权API方法的问题是,指针所有权没有定义良好的类型语义。你只是事先不知道——除非你把你的API命名得像容器一样笨拙——加上所有权——转移。此外,这意味着某些API可以进行所有权转移,但无法通过类型检查发现。这对于语言绑定尤其重要,因为它们需要知道所有权转移规则

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

我的解决方案有一个我看不到的缺陷 您的解决方案的问题在于,您必须实现两个功能:

容器\添加\子对象。 容器\添加\子对象\移动\所有权。 考虑一个不想移动所有权的情况。在这种情况下,您有两种选择:

在将对象移动到函数中之前增加对象的引用计数: 容器\u添加\u子对象\u移动\u所有者容器,g\u对象\u引用子对象

添加另一个不移动所有权的函数: 容器添加子容器,子容器

对于浮动引用,您只有一个函数可以同时适用于这两种情况

浮动引用的概念是一个糟糕的设计决策。 就我个人而言,是的,这是一个糟糕的设计。您使用移动所有权的解决方案比使用浮动引用的解决方案更清晰,即使您必须创建两个函数,但我会为移动函数命名,例如container\u add\u child\u mv

对于浮动引用,您必须考虑g_object_ref_sink或只是g_object_ref。对于浮动引用,您必须考虑g_object_ref

即使是GLib文档也对浮动引用有一个明确的定义:

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