处理这种情况最简洁的方法是什么:
func a() string {
/* doesn't matter */
}
b *string = &a()
这会生成错误:
不能取一个()的地址
我的理解是,如果采用地址,Go会自动将局部变量提升到堆中。这里很清楚,要采用返回值的地址。处理这个问题的惯用方法是什么?
地址操作符返回指向具有“home”的东西的指针,例如,一个变量。代码中表达式的值是“无家可归者”。如果你真的需要一个*字符串,你必须分两步完成:
tmp := a(); b := &tmp
请注意,虽然* string的用例完全有效,但很多时候使用它们都是错误的。在Go中,string
是一个值类型,但是传递一个便宜的(指针和int)。 String的值是不可变的,改变了“home”指向的*string
更改,而不是字符串值,所以在大多数情况下根本不需要*string
。
请参阅Go language spec的相关部分。 &
只能用于:
你拥有的不是那些,所以它不起作用。
即使你能做到,我也不确定它意味着什么。取一个函数调用的结果地址?通常,您将某事物的指针传递给某人,因为您希望它们能够分配给指向的事物,并查看原始变量中的更改。但是函数调用的结果是暂时的;没有其他人“看到”它,除非你先把它分配给它。
如果创建指针的目的是创建具有动态生命周期的东西,类似于new()
或获取复合文字的地址,那么您可以将函数调用的结果分配给变量并获取该地址。
最后,您建议Go应该允许您获取任何表达式的地址,例如:
i,j := 1,2
var p *int = &(i+j)
println(*p)
当前的Go编译器打印错误:cannot take the address of i + j
在我看来,允许程序员获取任何表达式的地址:
将编译器和规范复杂化似乎适得其反。
我最近被打成了类似的东西。
首先在你的例子中谈论字符串是一种分心,使用结构代替,重写它像:
func a() MyStruct {
/* doesn't matter */
}
var b *MyStruct = &a()
这将无法编译,因为您无法获取()的地址。这样做:
func a() MyStruct {
/* doesn't matter */
}
tmpA := a()
var b *MyStruct = &tmpA
这将编译,但是你已经在堆栈上返回了一个MyStruct,在堆上分配了足够的空间来存储MyStruct,然后将内容从堆栈复制到堆中。如果你想避免这种情况,那就这样写:
func a2() *MyStruct {
/* doesn't matter as long as MyStruct is created on the heap (e.g. use 'new') */
}
var a *MyStruct = a2()
复制通常很便宜,但这些结构可能很大。更糟糕的是,当您想要修改结构并让它“坚持”时,您无法复制然后修改副本。
无论如何,当你使用返回类型的接口{}时,它会变得更加有趣。 interface {}可以是struct或指向struct的指针。出现了同样的复制问题。
a()
没有指向变量,因为它在堆栈上。你不能指向堆栈(为什么你呢?)。
如果你愿意,你可以这样做
va := a()
b := &va
但是你真正想要实现的目标有点不清楚。
猜你需要更有效的C ++帮助;-)
Temp obj和rvalue
“C ++中的真正临时对象是不可见的 - 它们不会出现在您的源代码中。每当创建非堆对象但未命名时,它们就会出现。这些未命名的对象通常出现在以下两种情况之一中:当应用隐式类型转换以使函数调用成功时以及函数返回对象时。
来自Primer Plus
lvalue是一个数据对象,可以通过用户(命名对象)通过地址引用。非左值包括文字常量(除了引用的字符串,由其地址表示),具有多个术语的表达式,例如(a + b)。
在Go lang中,字符串文字将转换为StrucType
对象,该对象将是一个不可寻址的临时结构对象。在这种情况下,Go中的地址不能引用字符串文字。
好吧,最后但并非最不重要的一个例外,你可以获取复合文字的地址。天哪,真是一团糟。
在分配给一个新变量时,你无法直接获得结果的引用,但是你只需预先声明你的“b”指针就可以通过惯用的方式在不使用临时变量(它无用)的情况下执行此操作 - 这是你错过了真正的一步:
func a() string {
return "doesn't matter"
}
b := new(string) // b is a pointer to a blank string (the "zeroed" value)
*b = a() // b is now a pointer to the result of `a()`
*b
用于取消引用指针并直接访问保存数据的内存区域(当然,在堆上)。