0

我习惯了 C 和指针的使用。我知道你可以用 C# 中的指针做很多事情,但是垃圾收集越来越烦人。是否可以创建指向对象的指针,并以某种方式将指针链接到对象,这样只要指针还活着,对象就不会被清理?有什么谎言

unsafe void* Function1 () {
 SomeStruct s = new SomeStruct();
 void* ptr = (void*) &s;
 return ptr;
}

main() {
  void* p = Function1();
  p->field = 3;
}

当我尝试这样做时,对象很好,并且指针在 Function1 中工作,但是一旦函数退出,尽管指针有效,对象就被销毁了。就垃圾收集器而言,如果有某种方法可以将两者联系起来,那就太棒了。

4

3 回答 3

2

假设您的类型SomeStruct名称不是很糟糕,实际上是 a struct,那么您正在堆栈上为它分配内存。

当您从该方法返回时,分配该结构的堆栈帧被删除,因此在该方法之外该结构根本不再存在。您无法阻止垃圾收集器将其删除,因为不是垃圾收集器将其删除。它是从执行此操作的方法返回的。

请注意,structC# 中的 a 与 C 中的 a 是不同的概念struct。在 C# 中,结构始终是值类型,而在 C 中,它可以是值类型或引用类型,具体取决于您如何使用它。

如果要保留该值,则可以将其装箱以将其保留在堆上。您返回对装箱值的引用,而不是指针,因为垃圾收集器不关心指针,只关心引用:

object Function1 () {
  SomeStruct s = new SomeStruct();
  // box the value:
  object o = s;
  return o;
}

main() {
  object p = Function1();
  // unbox the value:
  SomeStruct s = ((SomeStruct)p);
  s.field = 3;
}

您当然可以传递结构而不是将其放在堆上:

SomeStruct Function1 () {
  return new SomeStruct();
}

main() {
  SomeStruct p = Function1();
  p.field = 3;
}

如果您确实需要将 存储struct在堆上,那么您应该考虑将其class改为 a ,然后它会自动结束在堆上。

于 2012-10-26T21:23:51.570 回答
1

假设SomeStruct实际上struct不是值类型,并且在您的特定情况下它是在堆栈上分配的。请注意,struct在 C 和structC# 中具有不同的含义。

于 2012-10-26T21:22:50.353 回答
1

引用计数并停止分配被垃圾收集直到不再使用的指针是reference. 使用引用,您根本不可能需要指针或unsafe代码。

C# 不是 C,所以要小心尝试编写 C 代码 - 你需要学习 C# 并意识到尽管它们明显相似,但语言之间存在一些非常大的差异。

于 2012-10-26T21:24:06.920 回答