转让所有权(Genie/Vala)

问题描述 投票:0回答:3

有一个简单的例子:

struct MyStruct
    a: int
    b: int

def my_proc(): unowned list of MyStruct
    var result = new list of MyStruct
    var my_struct = MyStruct()
    for var i = 1 to 10
        my_struct.a = i
        my_struct.b = i*i
        result.add(my_struct)
    return result

init
    pass

在编译此代码时,会出现错误:“未声明具有强引用的局部变量用作返回值和方法返回类型以转移所有权”。如何更改编译成功的代码?

compiler-errors vala genie
3个回答
2
投票

是什么让你认为返回值应该是无主的?

如果是因为没有

unowned
,Vala 编译器给出了
"error: 'MyStruct' is not a supported generic type argument, use '?' to box value types"
那么你可以尝试使用
list of MyStruct?
。这“装箱”[1][2] 基本 C 数据类型,因此可以在底层 GObject 类型系统中使用。

如果是因为您阅读了教程以及“弱引用”、“无主引用”、“所有权转移”和“指针”部分,那么我认为您应该将这些主题视为高级主题。我认为它们应该在某个时候移动到一个单独的页面,以便那些想要深入了解 Genie 的人。

Vala 编译器和 Genie 都辅助内存管理。这意味着一切都会在后台为您处理好。 Vala 编译器具有合理的默认行为,因此您无需进行更改。

作为 Genie 程序员,您应该了解与 C 库接口的可空类型,并且在创建循环引用时引用计数可能会导致内存泄漏[3]。除此之外,对于那些真正想要深入了解 Genie 工作原理并修复问题的人来说,请查看 Genie 教程该部分中的主题。

结构体可以被认为是对象的先驱。结构是一种复合数据类型。 Vala/Genie 中结构的内存由堆栈上的 C 编译器处理[4]。这可能会给他们带来性能优势。然而,一般来说,最好对复合数据类型使用类,因为它们更适合底层的 GObject 类型系统。不过,如果您尝试大量优化某些代码以提高速度[5]或与使用结构的 C 库进行交互,您可能需要使用结构。

所以简短的答案是使用 Jens 的使用类的解决方案,除非你有充分的理由不这样做。

[1] - https://docs.gtk.org/gobject/boxed.html

[2] - Vala 接口泛型编译器错误

[3] - https://wiki.gnome.org/Projects/Vala/ReferenceHandling

[4] - https://wiki.gnome.org/Projects/Vala/Tutorial#Structs

[5] - http://zee-nix.blogspot.co.uk/2008/09/think-before-you-create-gobjects.html


1
投票

精灵列表实际上是“伪装”中的

Gee.List<T>
,它是一种类类型,因此它将被引用计数。

此外,类型推断的

var
变量当前始终是一个拥有的变量(Vala 错误跟踪器中有关于此的错误报告)。

所以

result
对类实例的强引用。您不能将其作为无主引用返回。

我强烈建议您使用类而不是结构体

MyStruct

否则你将遇到内存管理问题(结构体不进行引用计数)。

您不必担心复制和所有权:

class MyStruct
    a: int
    b: int

def my_proc(): list of MyStruct
    var result = new list of MyStruct
    for var i = 1 to 10
        var my_struct = new MyStruct()
        my_struct.a = i
        my_struct.b = i*i
        result.add(my_struct)
    return result

init
    pass

编辑:如果您希望列表包含多个值,您还必须在循环内分配 my_struct!我已经更新了我的代码以反映这一点。


1
投票

在任何给定时间必须至少有一个对象的引用。在这里,您创建一个变量

result
,它具有对列表的引用。当你退货时,你坚持说它是
unowned list of MyStruct
。这意味着返回没有引用并且
result
超出了范围,因此列表现在没有对其的引用并将被释放。

您实际上返回了一个悬空引用。要么返回

list of MyStruct
,以便调用者拥有引用,要么将副本置于某种共享状态(全局变量或字段)。

© www.soinside.com 2019 - 2024. All rights reserved.