在设计和编写库时,我什么时候应该使用指针作为参数,什么时候不应该

  • 本文关键字:什么时候 指针 不应该 参数 pointers go
  • 更新时间 :
  • 英文 :


对不起,如果我的问题看起来很愚蠢。我的背景是PHP,Ruby,Python,Lua和类似的语言,我不了解现实生活中的指针。

从我在互联网上读到的内容以及我提出的一个问题的回答(指针什么时候是惯用语?),我已经理解:

  • 复制大型数据时应使用指针。而不是获取整个对象层次结构,而是接收其地址并访问它。
  • 当您在结构上有一个修改它的函数时,必须使用指针。

所以,指针似乎是一件好事:我应该总是将它们作为函数参数,因为它们是如此轻量级,如果我最终不需要修改结构上的任何内容也没关系。

然而,凭直觉看这句话,我能感觉到它听起来很令人毛骨悚然,但我不知道为什么。

那么,作为设计结构及其相关函数或只是函数的人,我应该何时收到指针?我应该在什么时候收到值,为什么?

换句话说,我的NewAuthor方法什么时候应该返回&Author{ ... },什么时候应该返回Author{ ... }?我的函数什么时候应该获取指向作者的指针作为参数,什么时候应该只获取类型 Author 的值(副本)?

指针和值都需要权衡。

一般来说,指针将指向系统中的某个其他内存区域。 无论是想要传递指向局部变量的指针的函数堆栈,还是堆上的某个位置。

func A() {
    i := 25
    B(&i) // A sets up stack frame to call B,
          // it copies the address of i so B can look it up later.
    // At this point, i is equal to 30
}
func B(i *int){
     // Here, i points to A's stack frame.
     // For this to execute, I look at my variable "i", 
     //   see the memory address it points to, then look at that to get the value of 25.
     // That address may be on another page of memory, 
     // causing me to have to look it up from main memory (which is slow).
     println(10 + (*i)) 
     // Since I have the address to A's local variable, I can modify it.
     *i = 30
}
指针

要求我在查看指针指向的数据时不断取消引用它们。 有时你不在乎。 其他时候,这很重要。 这实际上取决于应用程序。

如果该指针必须被大量取消引用(即:你传入一个数字以在一堆不同的计算中使用),那么你将继续付出代价。

与使用值相比:

func A() {
    i := 25
    B(i) // A sets up the stack frame to call B, copying in the value 25
    // i is still 25, because A gave B a copy of the value, and not the address.
}
func B(i int){
     // Here, i is simply on the stack.  I don't have to do anything to use it.
     println(10 + i) 
     // Since i here is a value on B's stack, modifications are not visible outside B's scpe
     i = 30
}

由于没有什么可以取消引用的,因此基本上可以自由使用局部变量。

如果这些值很大,则传递值的缺点会发生,因为将数据复制到堆栈不是免费的。

对于 int 来说,这是一种洗涤,因为指针是"int"大小的。 对于结构或数组,您正在复制所有数据。

此外,堆栈上的大对象会使堆栈变得特别大。 Go 通过堆栈重新分配很好地处理了这一点,但在高性能场景中,它可能对性能影响太大。

还有一个数据安全方面(不能修改我按值传递的内容),但我认为这在大多数代码库中通常不是问题。

基本上,如果你的问题已经可以通过ruby,python或其他没有值类型的语言来解决,那么这些性能的细微差别就无关紧要了。

通常,将结构作为指针传递通常会在学习语言时做"正确的事情"。

对于所有其他类型或要保留为只读的内容,请传递值。

这条规则也有例外,但最好在需要时学习这些,而不是试图一下子重新定义你的世界。 如果这是有道理的。

简单地说,你可以在任何你想要的地方使用指针,有时你不想改变你的数据。它可能代表抽象数据,并且您不想显式复制数据。只需传递值,让编译器完成其工作。

最新更新