此特定案例的结构或类[重复]

Posted

技术标签:

【中文标题】此特定案例的结构或类[重复]【英文标题】:Struct or Classes For This Specific case [duplicate] 【发布时间】:2013-09-27 11:01:19 【问题描述】:

凭借我目前所拥有的所有知识,我无法决定将哪个用于我的用例。

现在是 struct 的示例。

第一个类是这样的:

class Owner

  public A[] Kids;

  public Owner(int count)
  
    Kids = new A [count];

    // If I would use classes I would need to create new class for each item, right?
    // It would look like below and my worries are memory impacts because of new A()
    // for(int i = 0; i < count; Kids[i++] = new A());
  

第二个类是这样的:

class Node

  private Owner o;
  private int num;
  private A[] kids;

  public Node(Owner o, int num)
  
   this.o = o;
   this.num = num;
  

  public A[] Kids
  
    get
    
      this.kids = o.Kids[num].NextList;
      return this.kids;
    
  

A型是这样的

<struct or class> A

  public int Value;
  public A[] NextList;

现在的问题是,使用结构体时访问会比使用类时运行得更快吗?

由于我需要初始化每个类,所以在使用类时会产生内存开销吗?

在使用类时我需要注意杀死引用吗?

在这种情况下你会使用哪个家伙?

如果这是重复的或我做错了什么,我深表歉意。请在降级问题之前告诉我我做错了什么。我还是这个论坛的新手。

【问题讨论】:

A 是否曾经发生过变异,还是以不可变的方式使用?关于您的参考问题,您需要做的就是“放开”它们,以便它们有资格进行垃圾收集。我倾向于发现即使在结构可能稍微好一点的情况下,类也绰绰有余。这些天来,我越来越少有理由打扰struct 的东西。 我认为您高估了使用类的影响。我建议您选择最有意义的一个,并且只在出现性能问题时处理它们。正如 Donald Knuth 曾经说过的“过早的优化是万恶之源”。如果你真的很关心优化这个,我会分析它。测试两个场景并测量时间。 关于使用类或结构的优势有很多争论,几天前我因为建议使用结构而被否决,所以我可以理解你的紧张情绪。我认为答案将是“视情况而定”,并且取决于许多因素。我现在通常使用类,但我怀疑实际差异可以忽略不计。 默认值:如果你不能在类和结构之间做出决定,那么使用类。 @devhedgehog 另一个经常表达的建议是使struct 类型不可变。我也倾向于遵循这一点。在这种情况下坚持使用一个类。是的,类、所需的引用空间和 GC 问题存在“开销”,但 CLR 已针对这些任务进行了优化 - 这些是 CLR 的基本任务(它做得很好)。 【参考方案1】:

TL;DR:使用类。

由于您使用的是数组并且担心内存问题,因此需要记住一件事:

如果您有一个结构数组,则为该数组分配的总字节数将为sizeof(your struct) * number of elements

如果您有一个类数组,则为该数组分配的总字节数将为sizeof(reference) * number of elements(其中引用的大小对于 x86 为 32 位,对于 x64 为 64 位)。

可能在某些情况下会产生很大的不同。

如果数组的总大小超过 85,000 字节,那么它将被放置到大对象堆中。否则,它会进入普通堆。这可能意味着使用结构会导致某些数组超过 85,000 字节的阈值,而如果您使用类,它们将不会达到该阈值。

大对象堆上的项目在垃圾收集 (*) 期间不会被压缩,因此如果您有太多大对象,您可能会遇到内存碎片问题。

请注意,这也适用于许多其他集合(例如 List&lt;T&gt;),因为它们在实现中使用数组。

在大多数情况下,使用类而不是结构的开销可以忽略不计,无论如何,如果您认为它会导致问题,您应该确定代码。

因此,您通常应该只使用一个类。

还有一点需要注意:

如果你有一个结构列表,你不能改变列表中单个元素的属性,除非用更新的元素替换整个元素。

所以这是不可能的:

List<MyStruct> list = new List<MyStruct>();
... init list
list[0].Value = 1; // Compile error for structs, no error for classes.

但这不应该是一个问题——因为你的结构总是不可变的,所以你不会一开始就尝试这样做,对吧? ;)


(*) 这不再严格意义上的正确了。 .Net 4.51 引入了一种允许下一次垃圾收集移动大对象的方法,但这必须以编程方式启动。

http://blogs.msdn.com/b/mariohewardt/archive/2013/06/26/no-more-memory-fragmentation-on-the-large-object-heap.aspx

【讨论】:

我没有结构列表,只有数组。正如您在我的示例中看到的那样,Node 类包含 Kids。如果我把它做成一个结构,我不会关心释放引用,对吧?如果我选择结构,访问 Node.Kids 会更快吗? @devhedgehog 你也不关心类的“释放参考”。当您无法从任何地方到达某个对象时,它会自动符合垃圾回收条件。 @downvoter:请解释问题所在;否则反对票是毫无意义的。 当我不需要节点中的所有者时,我需要将所有者设置为空。否则节点将始终留在那里,因为所有者是主类。无论我是否不再使用该节点,它都会留在那里。据我了解GC。看看我的例子。我在节点中持有所有者的实例。当不再需要节点时,我应该释放实例对吗? @devhedgehog 是的,但我以为你在谈论名为A 的类型——这就是你正在考虑创建一个结构的类型,对吧? Owner 已经是一个类类型。

以上是关于此特定案例的结构或类[重复]的主要内容,如果未能解决你的问题,请参考以下文章

结构或类以及公共数据呢?

结构或类中的数组初始化

案例分析:设计模式与代码的结构特性

在结构或类中使用智能指针

哪一个是最好的方法类或结构?在 C++ [重复]

在 Metal File 中访问 swift 结构或类