我有一个关于存储数据及其内存占用的基本问题。
我有一个List<t>
来存储我需要的基础对象。类型t有一个int id来定义它,以及其他字段。
我现在有一本词典。如果我创建一个Dictionary<t, int>
,其中t是值的对象,那么内存分配是否会高得多,如果我创建Dictionary<int, int>
,即存储t对象的副本,或者仅存储是否会再次存储?
由于
答案 0 :(得分:13)
这取决于T
是什么。如果T
是引用类型(即class
),则只有引用将存储在字典中。如果T
是值类型(struct
),则会存储副本。
答案 1 :(得分:5)
引用类型在传递它们时不会创建重复的对象。在封面下,基本上你是在传递指针。因此,如果您有N个对象,则每个对象将具有N x个内存+引用每个对象所需的内存。这与这些引用的存储容器无关,在您的情况下是字典。您将为字典带来一些内存成本,但如果您创建了另一个字典并将所有相同的对象放入其中,则内存中只有2x字典内存成本和一组对象。这是在使用引用类型时。
MyObject object = new MyObject(); // one object created in memory
MyObject object2 = object; // still only one object created in memory, but we have two references now
值类型在内存中始终是唯一的。因此,如果您创建System.Int32的字典,然后创建字典的副本,您也将拥有字典中每个值的副本。
int myInt = 5; // one int created in memory
int myInt2 = myInt; // two ints have been created in memory
因此,让我们弄清楚为某些场景分配了哪些内存块:
// two value types
Dictionary<int, int> myDictionary1 =
1 x Dictionary
N x int <key>
N x int <value>
Dictionary<int, int> myDictionary1 +
Dictionary<int,int> myDictionary2 (clone of 1) =
2 x Dictionary
2N x int <key>
2N x int <value>
// reference types
Dictionary <string, MyObject> myDictionary3 =
1 x Dictionary
N x string Reference
N x string instance (if they are all unique)
N x Object Reference
N x Object instance (if they are all unique)
Dictionary <string, MyObject> myDictionary3 +
Dictionary <string, MyObject> MyDictionary4 (clone of 3) =
2 x Dictionary
2N x string reference
1N x string instance (if they are all unique)
2N x Object reference
1N x Object instance (if they are all unqiue)
你的情景:
Dictionary<int, MyObject> myDictionary5
1 X Dictionary
N X key
N X value reference
N X value object
Dictionary<int, MyObject> myDictionary5 +
Dictionary<int, MyObject> myDictionary6 (clone of 5) =
2 x Dictionary
2N x key
2N x value reference
1N x value objects
答案 2 :(得分:1)
仅存储对象的引用。内存分配很小。
答案 3 :(得分:1)
我假设您正在讨论特定的集合类型System.Collections.Generic.Dictionary<K,V>
。
您没有告诉我们您的类型't'是值类型还是引用类型。
如果是参考类型,例如class T { int id; ...}
,然后Dictionary<K,T>
将保留对您添加的对象的引用。
如果是值类型,例如struct T { int id; ...}
,然后Dictionary<K,T>
会保留您添加的值的副本。
快乐的黑客攻击。
答案 4 :(得分:0)
正如我在其他问题中提到的,在开发时分析内存可以使用此代码:
bool forceFullCollection = false;
Int64 valTotalMemoryBefore = System.GC.GetTotalMemory(forceFullCollection);
//call here your bulk of Dictionary operations and objects allocations
Int64 valTotalMemoryAfter = System.GC.GetTotalMemory(forceFullCollection);
Int64 valDifferenceMemorySize = valTotalMemoryAfter - valTotalMemoryBefore;
关于参数 forceFullCollection :“如果forceFullCollection参数为true,则此方法在系统收集垃圾并完成对象时返回之前等待一小段时间。间隔的持续时间是内部指定的限制通过完成的垃圾收集周期的数量和周期之间恢复的内存量的变化。垃圾收集器不保证收集所有无法访问的内存。“ GC.GetTotalMemory Method
祝你好运!;)