Cache variables stored in array = better performance of retrieval?
考虑C指针并使用以下代码引用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class Content {
public Content (){} //empty constructor
} //end of Content class, emptiest class ever
public class Variants {
Content x ;
public Variants (){ //Variants constructor
x = new Content (); //point x of this instance towards a Content object
}
} //end of Variants class
void main (){
Contents [] v = new Contents [1]; //array for storing a variable coming from a Variants object
v [0] = ((Variants )new Variants ()).x; //store x of the
//instance of Variants in our single cell.
Print (typeof(v [0]))
}//end of main() |
这是一个有效的声明:v[0] = ((Variants)new Variants()).x;还是会泄露物体?
和
v[0]是否指向x引用的对象?换句话说,当我们说Print(typeof(v[0]))时,我们是直接跳到x引用的对象,还是意味着从变量对象到它的x变量的移动?
如果计算机确实必须移动到variants实例,然后移动到x,正如我们提到的第0个单元格(由于值存储到数组中的方式)。打印速度会更快吗?
1 2 3 4 5 6
| Variants temp = new Variants ()
Contents cTemp = temp .x; //reference variable to point directly at x
v [0] = cTemp ; //feed in this pointer, not Variants.x instruction
Print (typeof(v [0])) |
- C不会泄漏物体。最接近内存泄漏的是"pack rat";也就是说,保留对不再真正需要的对象的引用。就你的问题而言,并不清楚你在问什么,但是在C语言中,和其他语言中的指针/引用一样,引用是引用,总是指向特定的对象。即使你从其他地方得到了这个参考,也没有其他地方的"记忆",你仍然只是在参考这个对象。
- 所以数组的第0个单元格将直接指向x的地址,并且不会导致通过指针移动的开销,因为它们中不需要任何东西?谢谢,如果你提出这个问题,我可以接受
- 是的,没有"指点旅行"。你得到了对你想要的对象的引用,并且这个引用总是直接指向那个对象。(卢卡斯的回答对我来说很好,所以我不需要再加一个了。)
- 谢谢,这真是个好消息。
第一层不会漏水。它所做的就是创建一个variant,然后创建一个content,保存内容并丢弃变量,在其他时候这些变量将被垃圾收集。不会无限期保存内存。顺便问一下,为什么不直接创建内容?此外,行中的强制转换是不必要的,因为new运算符已经键入variant,因此强制转换是多余的。
关于Print(typeof(v[0]))。首先,我猜你说的是Console.WriteLine对吧?然后,typeof调用甚至不会编译。它需要的是类型,而不是变量或对象引用。它可以是编译时值的typeof(Content),也可以是获取变量表达式类型的v[0].GetType()调用。此外,它不会像您所暗示的那样只返回一个字符串,而是返回一个完整的Type对象,其中包含有关类的完整信息。
到了表演的地步。我对什么更快或更慢有疑问。虽然这个变量需要2个"跃点"才能到达常量,但是使用数组还需要访问Array类的索引器,这可能会增加一些开销。使用一个简单的局部变量最有可能获得几个循环,在您的示例代码中,这是完全可能的。但要真正回答速度问题,需要一个测试和基准。其他一切都只是猜测,或多或少受过教育,但只是猜测。编译器还可以优化所有这些帐户,使它们最终相等。另外,考虑到这种差异(如果有的话)很可能是最小的,并且只有当这种代码在一个紧密的循环中被调用时才是显著的和相关的。
我想你有C++背景,并试图把它改编成C语言。大多数事情都完全不同(特别是内存管理和泄漏)。除了名称和语法之外,这两种语言几乎没有任何共同之处,但是编程模型却大不相同。
- 谢谢您!是的,配置文件很好,只是不想最终得到难以重写的东西,例如递归/堆栈形式。事实上,最终的代码必须被多个生物每秒调用60次,这有助于人工智能
- 关于C++背景的好点。如果是这样的话,你应该像C++指针一样对待C引用。(你也可以在C中获得真正的指针,但它们有不同的用途)
Is this a valid statement: v[0] = ((Variants)new Variants()).x; or it will leak objects?
是的,这是一个有效的声明,不会泄露任何信息。但这会缩短:
1
| v [0] = (new Variants ()).x; |
Does v[0] point to the object referenced by x?
是的,在那一点上,您的Variants对象可能已经被垃圾收集了(或者没有,您不知道),因为您没有保留任何对它的引用。
C中没有物体泄漏的情况。如果创建许多可访问的对象,例如通过将对象添加到静态列表中而从不删除它们,则可能会发生内存泄漏。但是,如果任何对象无法从其他代码访问,它迟早会被垃圾收集。
即使你有一个对象图,比如A点指向B,B点指向A,但是没有其他可到达的对象指向A或B,这两个对象都将被收集。
另外,不要担心这一点的性能,对象取消引用的影响非常小。
- 请注意,"new variants().x"甚至更短,而且也可以正常工作。:)
- @彼得的确如此,但我不喜欢它,因为每次我读它时,它都会引起四分之一秒的混乱;)
- 顺便问一下,为什么要收集对象,我们不是在存储对它的一个变量的引用吗?不过,它会保留X引用的内容实例吗?
- @尴尬的是,在这一点上,这被称为微观优化(我甚至会说纳米优化)。我想你弄错了。如果您需要更高的性能,您可能需要重新检查您首先使用的数据结构,因为这将使您获得或释放大部分数据结构。例如,您是在迭代数组而不是使用HashSet吗?也许你真正需要的是某个时刻的Dictionary?使数据结构正确(1000个对象很少)。此外,您可以使用分析器来查找瓶颈,它们通常隐藏在您无法预料的地方。
- 不,您存储的是对它也引用的对象的引用。"变量"x不相关。这就是variants对象保存引用的地方,它不是对象本身。
- @尴尬的是,Contents实例不是Variants实例的一部分。Variants实例仅引用Contents实例,仅此而已。
- 重申卢卡斯的观点:第一要紧。现在您应该集中精力纠正代码。如果它足够快,你就完了。如果速度太慢,那么您可以花时间研究原因,使用适当的工具(比如分析器……绝对不是直觉和猜测)。存储一个包含多个值的对象数组或单个值的多个数组的问题确实出现了,但只出现在非常特殊的场景中。在你知道你真的需要之前,尝试为那个场景进行优化是浪费。
- 我们的大多数代码是按索引+二进制搜索和通用列表排列的数组。感谢您提醒我们哈希集和字典,我们也会考虑它们的!
- 在大多数有许多对象的场景中,二进制搜索可能比使用哈希代码的正确结构慢得多。在我的头脑中,我有两个对您可能感兴趣的答案:关于集合语义和相等比较器。