Address of a temporary in Go?

后端 未结 8 742
不知归路
不知归路 2021-02-01 13:24

What\'s the cleanest way to handle a case such as this:

func a() string {
    /* doesn\'t matter */
}

b *string = &a()

This generates the

相关标签:
8条回答
  • 2021-02-01 13:52

    a() doesn't point to a variable as it is on the stack. You can't point to the stack (why would you ?).

    You can do that if you want

    va := a()
    b := &va
    

    But what your really want to achieve is somewhat unclear.

    0 讨论(0)
  • 2021-02-01 13:54

    The address operator returns a pointer to something having a "home", e.g. a variable. The value of the expression in your code is "homeless". if you really need a *string, you'll have to do it in 2 steps:

    tmp := a(); b := &tmp
    

    Note that while there are completely valid use cases for *string, many times it's a mistake to use them. In Go string is a value type, but a cheap one to pass around (a pointer and an int). String's value is immutable, changing a *string changes where the "home" points to, not the string value, so in most cases *string is not needed at all.

    0 讨论(0)
  • 2021-02-01 13:55

    See the relevant section of the Go language spec. & can only be used on:

    1. Something that is addressable: variable, pointer indirection, slice indexing operation, field selector of an addressable struct, array indexing operation of an addressable array; OR
    2. A composite literal

    What you have is neither of those, so it doesn't work.

    I'm not even sure what it would mean even if you could do it. Taking the address of the result of a function call? Usually, you pass a pointer of something to someone because you want them to be able to assign to the thing pointed to, and see the changes in the original variable. But the result of a function call is temporary; nobody else "sees" it unless you assign it to something first.

    If the purpose of creating the pointer is to create something with a dynamic lifetime, similar to new() or taking the address of a composite literal, then you can assign the result of the function call to a variable and take the address of that.

    0 讨论(0)
  • 2021-02-01 13:59

    At the time of writing this, none of the answers really explain the rationale for why this is the case.

    Consider the following:

    
    func main() {
        m := map[int]int{}
        val := 1
        m[0] = val
        v := &m[0] // won't compile, but let's assume it does 
        delete(m, 0)
        fmt.Println(v)
    }
    

    If this code snippet actually compiled, what would v point to!? It's a dangling pointer since the underlying object has been deleted.

    Given this, it seems like a reasonable restriction to disallow addressing temporaries

    0 讨论(0)
  • In the end you are proposing that Go should allow you to take the address of any expression, for example:

    i,j := 1,2
    var p *int = &(i+j)
    println(*p)
    

    The current Go compiler prints the error: cannot take the address of i + j

    In my opinion, allowing the programmer to take the address of any expression:

    • Doesn't seem to be very useful (that is: it seems to have very small probability of occurrence in actual Go programs).
    • It would complicate the compiler and the language spec.

    It seems counterproductive to complicate the compiler and the spec for little gain.

    0 讨论(0)
  • 2021-02-01 14:08

    guess you need help from More effective Cpp ;-)

    Temp obj and rvalue

    True temporary objects in C++ are invisible - they don't appear in your source code. They arise whenever a non-heap object is created but not named. Such unnamed objects usually arise in one of two situations: when implicit type conversions are applied to make function calls succeed and when functions return objects.”

    And from Primer Plus

    lvalue is a data object that can be referenced by address through user (named object). Non-lvalues include literal constants (aside from the quoted strings, which are represented by their addresses), expressions with multiple terms, such as (a + b).

    In Go lang, string literal will be converted into StrucType object, which will be a non-addressable temp struct object. In this case, string literal cannot be referenced by address in Go.

    Well, the last but not the least, one exception in go, you can take the address of the composite literal. OMG, what a mess.

    0 讨论(0)
提交回复
热议问题