当前位置: 首页 > 面试题库 >

为什么Go禁止使用(&)映射成员的地址,却允许(&)slice元素?

周龙光
2023-03-14
问题内容

Go不允许使用地图成员的地址:

// if I do this:
p := &mm["abc"]
// Syntax Error - cannot take the address of mm["abc"]

理由是,如果Go允许使用此地址,则当地图后备存储增长或减少时,该地址可能变得无效,从而使用户感到困惑。

但是,当Go slice超出其容量时,它将被重新定位,但是Go允许我们获取slice元素的地址:

 a := make([]Test, 5)
 a[0] = Test{1, "dsfds"}
 a[1] = Test{2, "sdfd"}
 a[2] = Test{3, "dsf"}

 addr1 := reflect.ValueOf(&a[2]).Pointer()
 fmt.Println("Address of a[2]: ", addr1)

 a = append(a, Test{4, "ssdf"})
 addrx := reflect.ValueOf(&a[2]).Pointer()
 fmt.Println("Address of a[2] After Append:", addrx)

 // Note after append, the first address is invalid
 Address of a[2]:  833358258224
 Address of a[2] After Append: 833358266416

为什么Go这样设计?切片元素的地址有何特殊之处?


问题答案:

切片和贴图之间的主要区别在于:切片由后备数组支持,而贴图则没有。

如果地图增大或缩小,则指向地图元素的潜在指针可能会变成指向任何地方(未初始化的内存)的悬空指针。这里的问题不是“用户困惑”,而是它会破坏Go的主要设计元素:没有悬空的指针。

如果切片用完了容量,则会创建一个新的更大的后备阵列,并将旧的后备阵列复制到新的后备阵列中。并且旧的支持阵列 仍然 存在
。因此,从指向原始支持数组的“未成年人”切片中获得的任何指针仍然是指向有效内存的有效指针。

如果您有一个切片仍指向旧的支持阵列(例如,因为在将切片增长到超出其容量之前已复制了该切片),您仍将访问旧的支持阵列。这与切片元素的指针关系不大,但是切片是视图到数组中,并且数组在切片增长期间被复制。

注意,在切片收缩期间没有“减少切片的衬背阵列”。



 类似资料:
  • 问题内容: 这与为什么为什么不接受(&)映射成员的地址而允许(&)slice元素相同?但我对接受的答案不满意:“切片由后备数组支持,而映射则不支持。” 注意:现在,我已对上面提到的问题添加了自己的答案。 Map中的Access Struct问题(不带复制)甚至更好,但是它被接受的答案是您不能修改map中的struct值字段,因为您无法获取其地址(这是我的问题)。 就像切片一样,映射由内存结构(可能

  • 如果我有一个封装两个成员的结构,并基于另一个成员更新其中一个,那么只要我这样做就可以了: 也就是说,当我直接提到self时。b 。但当我将do\u stuff()更改为以下内容时: 编译器抱怨:<代码>无法将`*self`借用为不可变,因为` self `。a `也被借用为可变的。 如果我需要执行比返回成员更复杂的操作来获取a.do\u something()的参数,该怎么办?我必须创建一个按值返

  • 问题内容: 为什么会发生以下现象: 可执行示例 问题答案: 构建一个空切片,就像一个空数组一样,它是一个有效且有用的对象(在所有语言中,而不仅仅是在Go中)。 空切片还仍然指向基础数组,位置和容量,有时可以扩展: 另一方面,长度为负的切片不一致。它没有任何意义,因此被禁止。

  • 为什么Java不允许在接口中使用私有成员?有什么特别的原因吗?

  • 问题内容: 为什么在最终课程中允许受保护的成员? 这不应该是编译时错误吗? 编辑:正如人们指出的那样,您可以使用默认修饰符来获得相同的程序包访问权限。它的行为应该完全相同,因为protected是默认+子类,而final修饰符明确地拒绝了子类,因此我认为答案不只是提供相同的程序包访问。 问题答案: 该改性剂是必要的方法其覆盖从基类的方法,在没有那些构件暴露于所述。 通常,您可以引入很多不必要的规则

  • 如果我有一些琐碎的东西,比如(为了澄清,我并不是说这是一个好的实现,只是一个演示成员函数部分模板专门化失败的示例): 我无法通过执行以下操作来专门化每个功能: 不幸的是,C标准不允许: 14.5.5.31、类模板局部特化成员的模板参数列表应与类模板局部特化的模板参数列表匹配类模板局部特化成员的模板参数列表应与类模板局部特化的模板参数列表匹配。 因此,唯一的解决方案(据我所知)是使用类型特征或用样板