我想在我的知识中找出一些空白。从这开始。
示例(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”对象分配了一个新的记忆位置。
如果这是正确的,请纠正我,如果这是错误的,这意味着使用“朋友”而不是“家伙”更有效。
是否会出现“家伙”更好的情况?它可能取决于构造函数的实现吗?
答案 0 :(得分:9)
据我所知,每次我实例化朋友时,我都会在内存中重用相同的位置,覆盖现有的Person对象(如果存在)。
不,事实并非如此。您正在覆盖变量中的先前值 - 但这不是对象。这只是对象的引用。还有另一个对列表中对象的引用。对象本身根本不会被覆盖。您创建的每个对象都独立于其他对象。
就在循环内或循环外声明变量之间的区别而言,它没有太大区别。有一些差异:
我通常建议在最初需要的地方声明具有最小范围的变量 - 我发现最终会得到更清晰的代码。
答案 1 :(得分:2)
在循环内部和外部创建对象之间的内存差异是什么?
不,在两种情况下,你都会在循环内创建新的Person
个对象。你只是在循环中创建一个变量,在外面创建一个变量。这两者之间的唯一区别是,在循环完成后,friend
仍然包含对您在循环内分配的最后一个实例的引用。
据我所知,每次我实例化朋友时,我都会在内存中重用相同的位置,覆盖现有的Person对象(如果存在)。
不,事实并非如此。每次实例化Person
时,它完全取决于运行时存储该新实例的位置。你没有覆盖以前的实例,你所做的只是重用你用来引用每个新实例的变量。
删除对实例的所有引用后,garbage collector可以释放与该旧实例关联的内存,从而允许以后重用该内存。但是在这里,您将每个实例添加到列表中,因此在names
列表被清除或销毁(以及可能存在于其他地方的任何其他实例)之前不会收集它们。
答案 2 :(得分:0)
创建新朋友时,您不会重复使用内存位置。您创建新对象并将其分配给朋友变量。因此,你会忘记&#39;关于以前的朋友。
因此它没有更高的内存效率。如果你在for循环之后没有使用朋友,那么在内部定义朋友变量也就像你和家伙一样更清晰。
答案 3 :(得分:0)
据我所知,每次我实例化朋友时,我都会在内存中重用相同的位置,覆盖现有的Person对象(如果存在)。
这种理解是错误的。你打破了从friend变量到内存中对象的连接,但是内存中的前一个对象仍然存在。如果没有对该对象的其他引用,则符合条件进行收集,但无法保证何时进行收集。在这种情况下,您仍然具有对旧对象的现有引用(通过名称集合),因此代码中唯一的区别是创建并分配给friend
变量的最后一个对象仍然可以访问循环。