Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ruby-on-rails-3/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 临时进入者的地址?_Pointers_Return_Go_Temporary_Rvalue - Fatal编程技术网

Pointers 临时进入者的地址?

Pointers 临时进入者的地址?,pointers,return,go,temporary,rvalue,Pointers,Return,Go,Temporary,Rvalue,处理此类案件最干净的方法是什么: func a() string { /* doesn't matter */ } b *string = &a() 这将生成错误: 无法获取()的地址 我的理解是,如果取局部变量的地址,Go会自动将其提升到堆中。这里很清楚,返回值的地址将被获取。处理这个问题的惯用方法是什么?a()不指向堆栈上的变量。你不能指向堆栈(为什么?) 如果你愿意,你可以这样做 va := a() b := &va 但是您真正想要实现的目标有些不清楚。地址运

处理此类案件最干净的方法是什么:

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

b *string = &a()
这将生成错误:

无法获取()的地址

我的理解是,如果取局部变量的地址,Go会自动将其提升到堆中。这里很清楚,返回值的地址将被获取。处理这个问题的惯用方法是什么?

a()
不指向堆栈上的变量。你不能指向堆栈(为什么?)

如果你愿意,你可以这样做

va := a()
b := &va

但是您真正想要实现的目标有些不清楚。

地址运算符返回一个指针,指向具有“home”的对象,例如变量。代码中表达式的值为“无家可归”。如果您确实需要*字符串,则必须分两步完成:

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

请注意,虽然*string有完全有效的用例,但很多时候使用它们是错误的。在Go
string
中,string是一种值类型,但传递起来很便宜(指针和int)。字符串的值是不可变的,更改
*字符串
会更改“home”指向的位置,而不是字符串值,因此在大多数情况下根本不需要
*字符串。

请参阅<代码>&
只能用于:

  • 可寻址的东西:变量、指针间接寻址、切片索引操作、可寻址结构的字段选择器、可寻址数组的数组索引操作;或
  • 复合文字
  • 你所拥有的都不是,所以它不起作用

    即使你能做到,我也不知道这意味着什么。获取函数调用结果的地址?通常,您将某个对象的指针传递给某人,因为您希望他们能够分配给所指向的对象,并查看原始变量中的更改。但是函数调用的结果是临时的;除非您先将其分配给某个对象,否则其他人不会“看到”它


    如果创建指针的目的是创建具有动态生存期的对象,类似于
    new()
    或采用复合文字的地址,然后,您可以将函数调用的结果分配给一个变量,并获取该变量的地址。

    最后,您建议Go应允许您获取任何表达式的地址,例如:

    i,j := 1,2
    var p *int = &(i+j)
    println(*p)
    
    当前Go编译器打印错误:
    无法获取i+j的地址

    在我看来,允许程序员获取任何表达式的地址:

    • 似乎不是很有用(也就是说:在实际的围棋程序中,它似乎发生的概率很小)
    • 这将使编译器和语言规范复杂化

    将编译器和规范复杂化而没有什么好处似乎会适得其反。

    我最近为类似的事情纠缠不清

    在您的示例中,首先讨论字符串是一种分散注意力的方法,请改用struct,将其重新写入如下内容:

    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()
    
    复制通常很便宜,但那些结构可能很大。更糟糕的是,当您想要修改结构并使其“粘贴”时,您不能复制然后修改副本


    无论如何,当您使用返回类型的接口{}时,它会变得更加有趣。接口{}可以是结构或指向结构的指针。同样的复制问题也出现了。

    我想你需要更有效的Cpp的帮助

    温度对象和右值

    “强”> C++中的真正临时对象是不可见的,它们不出现在源代码中。每当创建非堆对象而未命名时,它们就会出现。此类未命名对象通常出现在两种情况之一:当隐式类型转换被应用以使函数调用成功时,以及函数返回对象时。 和来自Primer Plus的

    左值是一个数据对象,可通过用户(命名对象)通过地址引用。非左值包括文字常量(除了由地址表示的带引号的字符串)、具有多个术语的表达式,例如(a+b)

    在Go lang中,字符串文字将转换为
    structType
    对象,该对象将是不可寻址的临时结构对象。在这种情况下,Go中的地址不能引用字符串文字


    最后但并非最不重要的一个例外是,在go中,您可以获取复合文本的地址。天哪,真是一团糟。

    在分配给新变量时,您无法直接获得结果的引用,但您有一种惯用的方法,只需预先声明“b”指针即可实现这一点,而无需使用临时变量(这是无用的)-这是您错过的真正步骤:

    func a()字符串{
    return“没关系”
    }
    b:=new(string)//b是指向空白字符串(“归零”值)的指针
    *b=a()//b现在是指向`a()结果的指针`
    
    *b
    用于取消指针引用并直接访问存储数据的内存区域(当然是在堆上)


    玩一下代码:

    在写这篇文章时,没有一个答案能真正解释为什么会出现这种情况

    考虑以下几点:

    
    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)
    }
    
    如果这个代码片段真的被编译了,那么
    v
    会指向什么呢!?它是一个悬空指针,因为基础对象已被删除


    有鉴于此,不允许寻址临时变量或从
    a()返回
    *字符串似乎是一个合理的限制。您还可以获取复合文本的地址,它不需要“主”复合文本