MST
星途 面试题库

面试题:C#中指针和引用类型在内存管理上的主要区别

请详细阐述C#中指针和引用类型在内存管理方面的主要差异,包括它们在栈和堆上的存储方式,以及垃圾回收机制对它们的影响。
25.7万 热度难度
编程语言C#

知识考点

AI 面试

面试题答案

一键面试

1. 栈和堆上的存储方式

  • 指针
    • 存储位置:指针变量本身存储在栈上,它保存的是另一个变量在内存中的地址。例如,在C# 中使用unsafe代码定义指针int* ptr;ptr这个指针变量存于栈,它指向的实际int型数据存储位置不定,取决于具体分配情况。
    • 访问方式:通过指针直接操作内存地址来访问所指向的数据。如*ptr表示访问指针ptr所指向的内存位置的值。
  • 引用类型
    • 存储位置:引用类型的变量本身存储在栈上,而其实际的数据内容存储在堆上。例如string str = "Hello";str这个引用存于栈,而实际的字符串“Hello”存于堆。
    • 访问方式:通过栈上的引用找到堆上的数据进行访问。如对str操作,实际是通过栈上的引用找到堆上字符串数据操作。

2. 垃圾回收机制对它们的影响

  • 指针
    • 手动管理:在C# 中使用指针时处于unsafe上下文,垃圾回收器不会自动管理指针指向的内存。开发人员需要手动负责分配和释放内存,否则容易造成内存泄漏。例如使用Marshal.AllocHGlobal分配非托管内存后,需调用Marshal.FreeHGlobal释放。
    • 与GC关系:指针操作可能干扰垃圾回收器正常工作,因为垃圾回收器基于特定算法移动和整理堆内存,指针可能指向已被移动或回收的内存区域,引发错误。
  • 引用类型
    • 自动管理:垃圾回收器负责管理引用类型在堆上分配的内存。当一个引用类型对象不再被任何变量引用(即没有可达路径),垃圾回收器会在适当时候回收该对象占用的内存。例如string str = "Hello"; str = null;,当str设为null后,原“Hello”字符串对象若没有其他引用,垃圾回收器会回收其内存。
    • 标记清除算法:垃圾回收器采用标记 - 清除等算法,首先标记所有可达对象,然后清除未标记(不可达)对象占用的内存空间,完成对引用类型内存的自动回收。