1

我想弥补我知识上的一些空白。从此开始。

示例(c#):

List<Person> names = new List<Person>();

Person friend = null;
for(int i = 0; i < 5; i++)
{
    friend = new Person();
    Person guy = new Person();

    guy.name = "Bob" + i;
    friend.name = "Bill" + i;

    names.Add(guy);
    names.Add(friend);
}

在这里,我在同一个循环中使用了两个 Person 对象,只是为了节省空间。

我的理解是,每次实例化朋友时,我都会重用内存中的相同位置,覆盖现有的 Person 对象(如果存在)。

而每个新的“家伙”对象都被分配了一个新的内存位置。

如果这是正确的,如果这是错误的,请纠正我,这意味着使用“friend”而不是“guy”更节省内存。

会不会有“家伙”会更好的情况?它可能取决于构造函数的实现吗?

4

4 回答 4

9

我的理解是,每次实例化朋友时,我都会重用内存中的相同位置,覆盖现有的 Person 对象(如果存在)。

不,事实并非如此。您正在覆盖变量中的先前值- 但这不是对象。这只是对对象的引用。列表中有另一个对该对象的引用。对象本身根本不会被覆盖。您创建的每个对象都独立于其他对象。

就在循环内或循环外声明变量的区别而言,并没有太大区别。有几点不同:

  • 如果它是在循环外声明的,您可以在为其分配新值之前在循环内使用该变量,这样您就可以看到以前的值
  • 如果它是在循环外声明的,您也可以在循环之后使用变量来读取最后分配的值
  • 如果它在循环外声明,并且您在循环内使用匿名函数,那么每个匿名函数都会捕获相同的变量。如果它在循环内,每个匿名函数将捕获一个不同的变量。如果此刻所有这些对你来说听起来像是 gobbledygook,你可能会忽略它
  • 如果它是在循环内声明的,那么在一个单独的块中,您可以声明一个具有相同名称的单独变量;如果它是在循环之外声明的,你就不能这样做。

我通常建议在您第一次需要它的时候声明具有最小范围的变量 - 我发现这最终会得到更清晰的代码。

于 2013-12-06T22:42:42.967 回答
2

在循环内部和外部创建对象之间的内存有什么区别?

不,在这两种情况下,您都是Person在循环内创建新对象。您只是在循环内部创建一个变量,在外部创建一个变量。这两者之间的唯一区别是循环完成后,friend仍然包含对您在循环内分配的最后一个实例的引用。

我的理解是,每次实例化朋友时,我都会重用内存中的相同位置,覆盖现有的 Person 对象(如果存在)。

不,事实并非如此。每次实例化 aPerson它完全取决于运行时存储该新实例的位置。您不会覆盖以前的实例,您所做的只是重用用于引用每个新实例的变量。

一旦删除了对实例的所有引用,垃圾收集器就可以释放与该旧实例相关联的内存,从而允许稍后重用该内存。names但是在这里,您将每个实例添加到列表中,因此在列表被清除或销毁(以及其他可能存在的任何其他实例)之前不会收集它们。

于 2013-12-06T22:44:05.040 回答
0

当您创建新朋友时,您不会重复使用内存位置。您创建新对象并将其地址分配给朋友变量。因此,您“忘记”了以前的朋友。

所以它不是更有效的内存。如果你在 for 循环之后不使用friend,那么在 for 内部定义friend 变量也更简洁,就像你对 guy 所做的那样。

于 2013-12-06T22:41:27.867 回答
0

我的理解是,每次实例化朋友时,我都会重用内存中的相同位置,覆盖现有的 Person 对象(如果存在)。

这种理解是错误的。您断开了从朋友变量到内存中对象的连接,但内存中的前一个对象仍然存在。如果没有对该对象的其他引用,它将有资格进行收集,但不能保证何时进行收集。在这种情况下,您仍然拥有对旧对象的现有引用(通过 names 集合),因此您的代码中唯一的区别是friend在循环之后仍然可以访问创建并分配给变量的最后一个对象。

于 2013-12-06T22:42:53.667 回答