转让所有权(Genie/Vala)
Transfer ownership (Genie/Vala)
有一个简单的例子:
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
在编译这段代码的情况下,出现错误:"Local variable with strong reference used as return value and method return type has not been declared to transfer ownership"。如何修改编译成功的代码?
Genie 列表实际上是 "disguise" 中的 Gee.List<T>
,它是 class 类型,因此它将被引用计数。
此外,类型推断 var
变量目前始终是拥有的变量(Vala 错误跟踪器中有关于此的错误报告)。
所以 result
对 class 实例的强引用。您不能 return 将其作为无主引用。
我强烈建议您使用 class 而不是 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!我已经更新了我的代码以反映这一点。
在任何给定时间必须至少有一个对象引用。在这里,您创建了一个变量 result
,它引用了一个列表。当你 return 它时,你坚持认为它是 unowned list of MyStruct
。这意味着 return 没有引用并且 result
超出范围,因此列表现在没有对它的引用并将被释放。
您实际上是在 return 悬空引用。 return list of MyStruct
,以便调用者具有引用或将副本置于某个共享状态(全局变量或字段)中。
是什么让您认为 return 值应该是无主的?
如果是因为没有 unowned
,Vala 编译器给出了 "error: 'MyStruct' is not a supported generic type argument, use '?' to box value types"
,那么您可以尝试使用 list of MyStruct?
。此 "boxes"[1][2] 基本 C 数据类型,因此可用于底层 GObject 类型系统。
如果是因为您阅读了教程和有关 "Weak References"、"Unowned References"、"Ownership Transfer" 和 "Pointers" 的部分,那么我认为您应该将这些主题视为高级主题话题。我认为他们应该在某个时候被移动到一个单独的页面,供那些想要深入研究 Genie 的人使用。
Vala 编译器等 Genie 协助内存管理。这意味着一切都在后台为您处理。 Vala 编译器具有合理的默认行为,因此您无需进行任何更改。
作为 Genie 程序员,您应该了解用于与 C 库交互的可空类型,并且在创建循环引用时引用计数会造成内存泄漏[3]。除了那些真正想深入了解 Genie 工作原理和解决问题的人之外,还可以查看 Genie 教程那部分中的主题。
结构可以被认为是对象的先驱。结构是一种复合数据类型。 Vala/Genie 中结构的内存由堆栈上的 C 编译器处理[4]。这可能会给他们带来性能优势。但是,一般来说,最好对复合数据类型使用 class,因为它们更适合底层的 GObject 类型系统。但是,如果您尝试大量优化某些代码以提高速度 [5] 或与使用结构的 C 库接口,则可能需要使用结构。
所以简短的回答是采用 Jens 使用 class 的解决方案,除非你有充分的理由不这样做。
[1] - https://developer.gnome.org/gobject/stable/gobject-Boxed-Types.html
[2] - Vala interface generics compiler error
[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
有一个简单的例子:
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
在编译这段代码的情况下,出现错误:"Local variable with strong reference used as return value and method return type has not been declared to transfer ownership"。如何修改编译成功的代码?
Genie 列表实际上是 "disguise" 中的 Gee.List<T>
,它是 class 类型,因此它将被引用计数。
此外,类型推断 var
变量目前始终是拥有的变量(Vala 错误跟踪器中有关于此的错误报告)。
所以 result
对 class 实例的强引用。您不能 return 将其作为无主引用。
我强烈建议您使用 class 而不是 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!我已经更新了我的代码以反映这一点。
在任何给定时间必须至少有一个对象引用。在这里,您创建了一个变量 result
,它引用了一个列表。当你 return 它时,你坚持认为它是 unowned list of MyStruct
。这意味着 return 没有引用并且 result
超出范围,因此列表现在没有对它的引用并将被释放。
您实际上是在 return 悬空引用。 return list of MyStruct
,以便调用者具有引用或将副本置于某个共享状态(全局变量或字段)中。
是什么让您认为 return 值应该是无主的?
如果是因为没有 unowned
,Vala 编译器给出了 "error: 'MyStruct' is not a supported generic type argument, use '?' to box value types"
,那么您可以尝试使用 list of MyStruct?
。此 "boxes"[1][2] 基本 C 数据类型,因此可用于底层 GObject 类型系统。
如果是因为您阅读了教程和有关 "Weak References"、"Unowned References"、"Ownership Transfer" 和 "Pointers" 的部分,那么我认为您应该将这些主题视为高级主题话题。我认为他们应该在某个时候被移动到一个单独的页面,供那些想要深入研究 Genie 的人使用。
Vala 编译器等 Genie 协助内存管理。这意味着一切都在后台为您处理。 Vala 编译器具有合理的默认行为,因此您无需进行任何更改。
作为 Genie 程序员,您应该了解用于与 C 库交互的可空类型,并且在创建循环引用时引用计数会造成内存泄漏[3]。除了那些真正想深入了解 Genie 工作原理和解决问题的人之外,还可以查看 Genie 教程那部分中的主题。
结构可以被认为是对象的先驱。结构是一种复合数据类型。 Vala/Genie 中结构的内存由堆栈上的 C 编译器处理[4]。这可能会给他们带来性能优势。但是,一般来说,最好对复合数据类型使用 class,因为它们更适合底层的 GObject 类型系统。但是,如果您尝试大量优化某些代码以提高速度 [5] 或与使用结构的 C 库接口,则可能需要使用结构。
所以简短的回答是采用 Jens 使用 class 的解决方案,除非你有充分的理由不这样做。
[1] - https://developer.gnome.org/gobject/stable/gobject-Boxed-Types.html
[2] - Vala interface generics compiler error
[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