在循环内部和外部创建对象之间的内存差异是什么

时间:2013-12-06 22:39:24

标签: c# memory-efficient

我想在我的知识中找出一些空白。从这开始。

示例(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对象(如果存在)。

而为每个新的“guy”对象分配了一个新的记忆位置。

如果这是正确的,请纠正我,如果这是错误的,这意味着使用“朋友”而不是“家伙”更有效。

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

4 个答案:

答案 0 :(得分:9)

  

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

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

就在循环内或循环外声明变量之间的区别而言,它没有太大区别。有一些差异:

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

我通常建议在最初需要的地方声明具有最小范围的变量 - 我发现最终会得到更清晰的代码。

答案 1 :(得分:2)

  

在循环内部和外部创建对象之间的内存差异是什么?

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

  

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

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

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

答案 2 :(得分:0)

创建新朋友时,您不会重复使用内存位置。您创建新对象并将其分配给朋友变量。因此,你会忘记&#39;关于以前的朋友。

因此它没有更高的内存效率。如果你在for循环之后没有使用朋友,那么在内部定义朋友变量也就像你和家伙一样更清晰。

答案 3 :(得分:0)

  

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

这种理解是错误的。你打破了从friend变量到内存中对象的连接,但是内存中的前一个对象仍然存在。如果没有对该对象的其他引用,则符合条件进行收集,但无法保证何时进行收集。在这种情况下,您仍然具有对旧对象的现有引用(通过名称集合),因此代码中唯一的区别是创建并分配给friend变量的最后一个对象仍然可以访问循环。