微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何获得对Nim中现有对象的安全引用?

如何解决如何获得对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 documentation中,ptr类型被称为“不安全”,建议仅用于低级操作。有一个“安全”引用类型ref,建议您使用ref,除非您真的想进行手动内存管理。

我不想执行手动内存管理,并且我希望Nim垃圾收集器为我处理这些参数的内存,但是我没有找到一种安全的方法ref这两个参数。

我真的希望能够用变量largesmall而不是param1来编写算法(比我展示的简单代码复杂得多)和param2。否则,如果我只能引用参数param1param2,而又不为其创建别名,则我必须复制并粘贴相同的算法两次,以分别处理案例param1.level < param2.levelparam1.level >= param2.level

在不使用ptr类型的情况下,是否存在一种更惯用的Nim方法来执行类似操作?

解决方法

除非执行对象的复制,否则您无法将 safe 对象转换为 unsafe ,反之亦然。

普通变量存储在堆栈中,因此当它们的功能范围存在时将被销毁,但是可以将引用存储到全局变量中并在以后访问。如果可能的话,为了安全起见,编译器/语言将需要知道某种从堆栈中提取变量的方法,以便在其作用域存在后仍然有效,或者在后面手动执行复制你的背,或其他神奇的东西。

这也是为什么获取变量地址不安全的原因。您不能保证其寿命,因为您可以将该地址存储在其他地方,以后再尝试使用。但是,就内存保证而言,这些变量至少应在proc调用期间保持活动状态,因此在该proc中使用这些地址别名应该是安全的,而不必担心。

也就是说,您可以重写代码以使用中间代理proc来执行检查,从而在每个 slot 中传递正确的变量。中间proc保证变量之一将始终很大,并且您可以避免使用不安全的引用:

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()
,
type
  MyObject = object
    level: int

proc subroutine(param1,param2: var MyObject) =
  if param1.level > param2.level:
    swap(param1,param2)
  echo param1.level
  echo param2.level

var
  p1 = MyObject(level: 7)
  p2 = MyObject(level: 3)

subroutine(p1,p2)
p2.level = 13
subroutine(p1,p2)

在这种情况下,Nim具有特殊的swap()proc。 Var参数在内部作为指针传递,因此在参数传递中不涉及复制,而swap应该使复制尽可能最佳。

当然,在某些情况下,使用ref对象而不是value对象可能会有好处。 Nim的引用是托管指针。您可以在教程中找到更多信息,我的一个位于http://ssalewski.de/nimprogramming.html#_value_objects_and_references

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。