2 回答
TA贡献1825条经验 获得超4个赞
指针和值都需要权衡。
一般来说,指针会指向系统中的其他一些内存区域。无论是想要将指针传递给局部变量的函数的堆栈还是堆上的某个位置。
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 或其他没有值类型的语言解决,那么这些性能上的细微差别并不重要。
一般来说,在学习语言时,将结构作为指针传递通常会做“正确的事情”。
对于所有其他类型或您希望保持为只读的内容,请传递值。
该规则也有例外,但最好是在需求出现时学习这些规则,而不是试图一次性重新定义您的世界。如果这是有道理的。
- 2 回答
- 0 关注
- 136 浏览
添加回答
举报