nim-lang - 如何在 Nim 中获得对现有对象的安全引用?
问题描述
我写了一个以两个对象为参数的Nim程序。var
它们每个都是一个带有int
字段的对象level
。在进行程序的实际工作之前,我想将参数按具有较大的顺序排列level
,所以我这样做:
proc subroutine(param1: var MyObject, param2: var MyObject) =
var large: ptr MyObject = param1.addr
var small: ptr MyObject = param2.addr
# If in wrong order by level, swap large and small
if large.level < small.level:
large = param2.addr
small = param1.addr
# The rest of the proc references, only variables large and small, e.g.,
large.level += 1
small.level += 2
这似乎适用于我的应用程序,但我注意到在Nim 文档中,该ptr
类型称为“不安全”,建议仅用于低级操作。有一个“安全”的引用类型,除非你真的想做手动内存管理,否则ref
建议使用它。ref
我不想进行手动内存管理,我希望 Nim 垃圾收集器为我处理这些参数的内存,但我看不到安全ref
的两个参数的方法。
我真的希望能够根据变量large
和small
而不是param1
和来编写算法(这比我展示的简单代码复杂得多) param2
。否则,如果我只能引用参数param1
和param2
,而不为它们创建这些别名,我将不得不复制并粘贴两次相同的算法来分别处理情况param1.level < param2.level
和param1.level >= param2.level
。
有没有更惯用的 Nim 方法来做这样的事情,而不使用ptr
类型?
解决方案
除非执行对象的副本,否则您无法将安全对象变为不安全对象,反之亦然。
普通变量存储在堆栈中,因此当它们的函数范围存在时将被销毁,但可以将引用存储到全局变量中并稍后访问。如果这是可能的,为了使其安全,编译器/语言将需要知道某种从堆栈中提取变量的方法,以便它在其范围存在后仍然有效,或者在你背后手动执行复制,或者其他一些神奇的事物。
这也是获取变量地址不安全的原因。您不能保证它的生命周期,因为您可以将该地址存储在其他地方并在以后尝试使用它。但是,就内存保证而言,这些变量至少应在您的 proc 调用期间保持活动状态,因此在该 proc 中使用这些地址别名应该是安全的,而无需担心。
也就是说,您可以重写代码以使用执行检查的中间代理 proc,从而在每个slot中传递正确的变量。中间过程保证变量之一总是很大,并且您可以避免使用不安全的引用:
type
MyObject = object
level: int
proc subroutine_internal(large: var MyObject, small: var MyObject) =
assert large.level >= small.level
large.level += 1
small.level += 2
proc subroutine(param1: var MyObject, param2: var MyObject) =
if param1.level < param2.level:
subroutine_internal(param2, param1)
else:
subroutine_internal(param1, param2)
proc main() =
var
a = MyObject(level: 3)
b = MyObject(level: 40)
subroutine(a, b)
echo a, b
main()
推荐阅读
- r - 在 bash 和 R 之间共享配置变量
- python - post方法是否所有功能都显示在Flask中
- api - Vue Axios API 对象到对象数组
- excel - 当 ActiveWorkbook.Close 发生时,程序主体中的更改不会被保存
- javascript - 如何将'objectName.variableName'作为字符串传递,然后将其作为变量进行操作?
- android - React Native FlatList 没有渲染 Axios API 请求
- json - 将 JSON 传递给 Thymeleaf 中的数据模型属性
- javascript - 使用javascript删除没有值的数组项
- sparql - 如何持久保存自动生成的 OWL 规则,或者至少不要一次将它们全部保存在内存中?
- c - 算术和几何平均误差解决方案