你如何解释C++指向C#/Java开发人员的指针?[已关闭]

2022-09-02 12:12:03

我是一名C#/Java开发人员,试图学习C++。当我试图学习指针的概念时,我被一个想法所震撼,即我以前一定处理过这个概念。如何仅使用 .NET 或 Java 开发人员熟悉的概念来解释指针?我真的从来没有处理过这个问题,它只是隐藏在我面前,还是我一直使用它而不这样称呼它?


答案 1

C++中的 Java 对象

Java 对象等效于C++共享指针。

C++指针就像一个没有内置垃圾回收的 Java 对象。

C++对象。

C++有三种分配对象的方法:

  • 静态存储持续时间对象。
    • 它们在启动时(在主退出之前)创建,并在主退出后死亡。
      有一些技术警告,但这是基础。
  • 自动存储持续时间对象。
    • 这些是在声明时创建的,并在超出范围时销毁。
      我相信这些就像C#结构
  • 动态存储持续时间对象

    • 这些指针是通过新的和最接近C#/Java对象(AKA指针
      创建的,从技术上讲,指针需要通过 手动销毁。但这被认为是不好的做法,在正常情况下,它们被放置在控制其寿命的自动存储持续时间对象(通常称为智能指针)中。当智能指针超出范围时,它将被销毁,其析构函数可以调用指针。智能指针可以作为细粒度垃圾收集器。deletedelete

      最接近Java的是shared_ptr,这是一个智能指针,它保留指针的用户数,并在没有人使用它时将其删除。


答案 2

你在C#中一直在“使用指针”,它只是对你隐藏。

我认为解决这个问题的最好方法是思考计算机的工作方式。忘记.NET的所有花哨的东西:你有内存,它只保存字节值,处理器,它只是对这些字节值做一些事情。

给定变量的值存储在内存中,因此与内存地址相关联。编译器不必一直使用内存地址,而是允许您从中读取并使用名称写入它。

此外,您可以选择将值解释为要在其中查找另一个值的内存地址。这是一个指针。

例如,假设我们的内存包含以下值:

Address [0] [1] [2] [3] [4] [5] [6] [7]
Data    5   3   1   8   2   7   9   4

让我们定义一个变量,编译器选择将其放在地址 2 处。可以看出,的值为 1。xx

现在,让我们定义一个指针,编译器已选择将其放在地址 7 处。的值为 。指向的值是地址 4 处的值,即 值 。获取该值称为取消引用pp4p2

需要注意的一个重要概念是,就内存而言,没有类型这样的东西:只有字节值。您可以选择根据需要解释这些字节值。例如,取消引用 char 指针将仅获得表示 ASCII 代码的 1 个字节,但取消引用 int 指针可能会获得 4 个字节,构成 32 位值。

再看一个示例,您可以使用以下代码在 C 中创建一个字符串:

char *str = "hello, world!";

它的作用是说明以下内容:

  • 在堆栈帧中为变量留出一些字节,我们将调用 该变量。str
  • 此变量将保存一个内存地址,我们希望将其解释为字符。
  • 将字符串第一个字符的地址复制到变量中。
  • (字符串“hello, world!”将存储在可执行文件中,因此在程序加载时将加载到内存中)

如果你要查看 的值,你会得到一个整数值,它表示字符串第一个字符的地址。但是,如果我们取消引用指针(即,查看它指向的内容),我们将得到字母“h”。str

如果递增指针 ,它现在将指向下一个字符。请注意,指针算术是缩放的。这意味着,当您对指针进行算术运算时,效果乘以它认为它所指向的类型的大小。因此,假设系统上的宽度为 4 个字节,则以下代码实际上会将 4 添加到指针中:str++;int

int *ptr = get_me_an_int_ptr();
ptr++;

如果你最终越过了字符串的末尾,没有人知道你会指向什么;但是您的程序仍然会尽职尽责地尝试将其解释为字符,即使该值实际上应该表示一个整数。但是,您可能正在尝试访问未分配给程序的内存,并且您的程序将作系统杀死。

最后一个有用的提示:数组和指针算术是一回事,它只是语法糖。如果您有一个变量 ,则char *array

array[5]

完全等价于

*(array + 5)