原始C代码用于遍历一棵树(深度优先),而无需递归,该树存储在数组中.然后,通过递增指针来遍历数组,除非满足特定条件,否则将指针设置为继续遍历的NextNode.当然,在C#中也可以通过以下方式实现:struct Node{ public int NextNode; ... // other fields} int是下一个节点数组中的索引.但是出于性能原因,我最终还是摆弄指针和fixed数组,无论如何都要避免边界检查,并且原始的C代码似乎更自然.解决方案 使用这种结构是否安全?我的意思是在堆上长期存储.是的.这样做通常是愚蠢的,痛苦的和不必要的,但是有可能. 据我了解,GC可以自由移动,在更新对已移动对象的引用的同时,它也可以更新指针吗?不. 这就是为什么我们让您将其标记为不安全. 我猜不是,这会使这种结构非常不安全,对吧?正确. 我敢肯定,还有其他更好的方法可以做到这一点,但可以称其为病态好奇心.肯定有. 是否可以保证指针始终指向您最初指向的内容?除非您确定会发生,否则不会.有两种方法可以做到这一点.方法之一:告诉垃圾收集器不要移动内存.有两种方法可以做到这一点: 使用固定"语句修复变量. 使用互操作服务在一个位置上创建要保留的结构的gc句柄. 执行上述任何一项操作很可能会破坏垃圾收集器的性能.方法二:不要引用垃圾回收器可能移动的内存.有两种方法可以做到这一点: 仅接受局部变量,值参数或堆栈分配的块的地址.当然,这样做时,您需要确保指针的生存期不会长于相关的堆栈帧,否则,您将引用垃圾. 从非托管堆中分配一个块,然后在该块内部使用指针.本质上,实现您自己的内存管理器.您需要正确实现新的自定义内存管理器.小心点.In C#, it's possible to declare a struct (or class) that has a pointer type member, like this:unsafe struct Node{ public Node* NextNode;}Is it ever safe (err.. ignore for a moment that ironic little unsafe flag..) to use this construction? I mean for longterm storage on the heap. From what I understand, the GC is free to move things around, and while it updates the references to something that's been moved, does it update pointers too? I'm guessing no, which would make this construction very unsafe, right?I'm sure there are way superior alternatives to doing this, but call it morbid curiosity.EDIT: There appears to be some confusion. I know that this isn't a great construction, I purely want to know if this is ever a safe construction, ie: is the pointer guaranteed to keep pointing to whatever you originally pointed it to?The original C-code was used to traverse a tree (depth first) without recursion, where the tree is stored in an array. The array is then traversed by incrementing a pointer, unless a certain condition is met, then the pointer is set to the NextNode, where traversal continues. Of course, the same can in C# be accomplished by:struct Node{ public int NextNode; ... // other fields}Where the int is the index in the array of the next node. But for performance reasons, I'd end up fiddling with pointers and fixed arrays to avoid bounds checks anyway, and the original C-code seemed more natural. 解决方案 Is it ever safe to use this construction? I mean for long term storage on the heap.Yes. Doing so is usually foolish, painful and unnecessary, but it is possible. From what I understand, the GC is free to move things around, and while it updates the references to something that's been moved, does it update pointers too?No. That's why we make you mark it as unsafe. I'm guessing no, which would make this construction very unsafe, right?Correct. I'm sure there are way superior alternatives to doing this, but call it morbid curiosity.There certainly are. is the pointer guaranteed to keep pointing to whatever you originally pointed it to?Not unless you ensure that happens. There are two ways to do that.Way one: Tell the garbage collector to not move the memory. There are two ways to do that:Fix a variable in place with the "fixed" statement.Use interop services to create a gc handle to the structures you wish to keep alive and in one place.Doing either of these things will with high likelihood wreck the performance of the garbage collector.Way two: Don't take references to memory that the garbage collector can possibly move. There are two ways to do that:Only take addresses of local variables, value parameters, or stack-allocated blocks. Of course, in doing so you are then required to ensure that the pointers do not survive longer than the relevant stack frame, otherwise, you're referencing garbage.Allocate a block out of the unmanaged heap and then use pointers inside that block. In essense, implement your own memory manager. You are required to correctly implement your new custom memory manager. Be careful. 这篇关于C#:使用指针类型作为字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!