Scala何时真正复制对象?

Scala何时真正复制对象?,scala,memory-management,reference,Scala,Memory Management,Reference,背景 我有一段代码如下所示: val big_obj = new BigObj big_obj.recs[5].foo() ... // other code big_obj.recs[7].bar() 问题 我想做这样的事情 val big_obj = new BigObj alias ref = big_obj.recs // looking for something like an alias ref[5].foo() ... // other code ref[7].bar()

背景

我有一段代码如下所示:

val big_obj = new BigObj
big_obj.recs[5].foo()
... // other code
big_obj.recs[7].bar()
问题

我想做这样的事情

val big_obj = new BigObj
alias ref = big_obj.recs  // looking for something like an alias
ref[5].foo()
... // other code
ref[7].bar()
因为我害怕复制大对象(来自C++)。但后来我意识到Scala可能很聪明,如果我这么做:

val big_obj = new BigObj
val ref = big_obj.recs  // no copies made?
编译器可能足够聪明,不会以任何方式复制,因为它都是只读的

问题

这让我想知道Scala的内存模型

在什么情况下会复制/不复制

我在寻找一个简单的答案或经验法则,当我处理真正的大对象时,无论何时我进行赋值,包括传递参数,我都能记住这个答案或经验法则。

就像Java(和python,可能还有很多其他语言)一样,复制从来都不是对象。指定对象或将其作为参数传递时,它仅复制对该对象的引用;实际对象只是位于内存中,并有一个额外的对象指向它。唯一会被复制的是原语(整数、双精度等)

正如您所指出的,这显然适用于不可变对象,但适用于所有对象,即使是可变对象:

scala> val a = collection.mutable.Map(1 -> 2)
a: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)

scala> val b = a
b: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)

scala> b += (2 -> 4)
res41: b.type = Map(2 -> 4, 1 -> 2)

scala> a
res42: scala.collection.mutable.Map[Int,Int] = Map(2 -> 4, 1 -> 2)

scala> def addTo(m: collection.mutable.Map[Int,Int]) { m += (3 -> 9) }
addTo: (m: scala.collection.mutable.Map[Int,Int])Unit

scala> addTo(b)

scala> a
res44: scala.collection.mutable.Map[Int,Int] = Map(2 -> 4, 1 -> 2, 3 -> 9)
就像Java(和python,可能还有很多其他语言)一样,拷贝从来都不是由对象构成的。指定对象或将其作为参数传递时,它仅复制对该对象的引用;实际对象只是位于内存中,并有一个额外的对象指向它。唯一会被复制的是原语(整数、双精度等)

正如您所指出的,这显然适用于不可变对象,但适用于所有对象,即使是可变对象:

scala> val a = collection.mutable.Map(1 -> 2)
a: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)

scala> val b = a
b: scala.collection.mutable.Map[Int,Int] = Map(1 -> 2)

scala> b += (2 -> 4)
res41: b.type = Map(2 -> 4, 1 -> 2)

scala> a
res42: scala.collection.mutable.Map[Int,Int] = Map(2 -> 4, 1 -> 2)

scala> def addTo(m: collection.mutable.Map[Int,Int]) { m += (3 -> 9) }
addTo: (m: scala.collection.mutable.Map[Int,Int])Unit

scala> addTo(b)

scala> a
res44: scala.collection.mutable.Map[Int,Int] = Map(2 -> 4, 1 -> 2, 3 -> 9)

一些早期的OO语言有“浅”复制与“深”复制的概念,并且在某些情况下实际上会复制对象。scala确实有一个“复制”方法,用于复制objects@ElectricCoffee:对象通常没有这样的方法。然而,case类确实如此。一些早期的OO语言有“浅”复制与“深”复制的概念,并且在某些情况下实际上会复制对象。scala确实有一个“复制”方法,用于复制objects@ElectricCoffee:对象通常没有这样的方法。然而,案例类确实如此。