【问题标题】:What is the underlying reason for not being able to put arrays of pointers in unsafe structs in C#?在 C# 中不能将指针数组放入不安全的结构中的根本原因是什么?
【发布时间】:2010-05-03 09:32:21
【问题描述】:

如果可以像在 C# 中那样将一组指向子结构的指针放在 C# 中的不安全结构中,那么构建复杂的数据结构而无需每个节点拥有一个对象的开销会容易得多,而且时间消耗更少,以及语法上更干净,更具可读性。

为什么不安全结构中的固定数组只允许由“值类型”而不是指针组成,是否存在深层架构原因?

我认为只有在结构中显式命名的指针必须是故意削弱语言的决定,但我找不到任何文档说明为什么会这样,或者不允许在结构中使用指针数组的原因,因为我会假设垃圾收集器不应该关心标记为不安全的结构中发生了什么。

相比之下,Digital Mars 的 D 可以优雅地处理结构和指针,我错过了无法快速开发简洁数据结构的情况;通过在 C# 中使引用抽象化,语言似乎已经消除了很多功能,即使指针至少在营销意义上仍然存在。

也许我期望语言随着时间的推移在有效表示复杂数据结构方面变得更加强大是错误的。

【问题讨论】:

    标签: c# pointers d unsafe struct


    【解决方案1】:

    一个非常简单的原因:dotNET 有一个压缩垃圾收集器。它移动东西。所以即使你可以创建这样的数组,你也必须pin每个分配的块,你会看到系统慢到爬行。

    但是您正在尝试基于假设进行优化。 dotNET 中对象的分配和清理经过高度优化。因此,首先编写一个工作程序,然后使用分析器找到您的瓶颈。它很可能不是您的对象的分配。

    编辑,回答后半部分:

    也许我对语言的期望是错误的 在代表方面变得更加强大 高效的复杂数据结构 随着时间的推移。

    我认为 C#(或任何托管语言)在表示方面更强大 复杂的数据结构(高效)。通过从低级指针更改为垃圾收集引用。

    【讨论】:

    • 这不可能是原因,因为您可以很好地在不安全结构中使用指向其他不安全结构的指针(以这种方式创建二叉树结构没有问题......)该限制仅适用于数组在不安全的结构(所谓的固定大小缓冲区)中,我认为原因并不明显(请参阅我的回复以获得可能的解释)
    【解决方案2】:

    我只是在猜测,但这可能与针对不同目标平台的不同指针大小有关。似乎 C# 编译器直接使用元素的大小进行索引计算(即没有 CLR 支持计算固定大小的缓冲区索引...)

    无论如何,您都可以使用 ulongs 的数组并将指针投射到它:

    unsafe struct s1
    {
      public int a;
      public int b;
    }
    
    unsafe struct s
    {
      public fixed ulong otherStruct[100];
    }
    
    unsafe void f() {
      var S = new s();
      var S1 = new s1();
      S.otherStruct[4] = (ulong)&S1;
      var S2 = (s1*)S.otherStruct[4];
    }
    

    【讨论】:

      【解决方案3】:

      在结构中放置一个固定的指针数组会很快使其成为结构的不良候选者。结构体的推荐大小限制为 16 字节,因此在 x64 系统上,您只能在数组中放置两个指针,这是毫无意义的。

      您应该为复杂的数据结构使用类,如果您使用结构,它们的使用会变得非常有限。例如,您将无法在方法中创建数据结构并返回它,因为它会包含指向不再存在的结构的指针,因为它们在方法的堆栈框架中分配。

      【讨论】:

      • 有趣。能否给一些文章的链接,或者解释一下为什么是 16 字节?
      • @Alexander:这是微软在他们的指导方针中所说的:msdn.microsoft.com/en-us/library/y23b5415%28VS.71%29.aspx
      • 类将变得比结构更有效的大小阈值因使用模式而异。小于 16 字节的不可变类很少会比人为场景之外的结构更有效,但是对于许多使用模式,即使是“大”(64-256 字节)结构也可能优于类。对于某些使用模式,结构的“获胜余量”实际上会随着有效负载的增加而增加(前提是它们不会大到导致堆栈崩溃)。
      • @supercat:结构变得低效时的大小阈值取决于不同大小的结构如何工作。结构和类的性能并没有真正的可比性,因为它们的用途是如此不同。一个复杂的数据结构根本不应该是一个结构体。
      • @Guffa: 25 字节结构的执行速度通常比 24 字节结构慢 5% 以上[阈值曾经是 16 字节],但实际上构建结构的时间 any 大小并将其返回给一个方法,该方法将从其中复制数据然后放弃它,这将远远少于构造一个包含相同数据的不可变类对象的时间。类引用的复制成本更低,但这只有在它们被放弃之前被复制 时才有好处。如果不是,那么创建类对象的额外时间就被浪费了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 2020-12-09
      • 2017-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多