你如何将C ++指针解释为C#/ Java开发者?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (30)

我是试图学习C ++的C#/ Java开发人员。当我试图学习指针的概念时,我感到以前我必须处理这个概念。如何仅使用.NET或Java开发人员熟悉的概念来解释指针?我真的从来没有处理过这件事吗,它是隐藏给我的,还是我一直使用它而没有调用它?

提问于
用户回答回答于

Java中的C ++对象

一个Java对象相当于一个C ++共享指针。

C ++指针就像没有内置垃圾收集器的Java对象。

C ++对象。

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

  • 静态存储时间对象。
    • 这些是在启动时(main之前)创建的,并在主要退出之后死亡。 有一些技术警告,但这是基础知识。

  • 自动存储持续时间对象
    • 当它们超出范围而被宣布和销毁时,就会创建它们。 我相信这些就像C#结构

  • 动态存储时间对象
    • 这些是通过新的和最接近C#/ Java对象(AKA指针)创建的。 技术指针需要通过手动销毁delete。但这被认为是不好的做法,并且在正常情况下,它们被放入控制它们寿命的自动存储持续时间对象(通常称为智能指针)中。当智能指针超出范围时,智能指针被销毁,析构函数可以调用delete指针。智能指针可以作为细粒度的垃圾收集器。 离Java最近的是shared_ptr,这是一个智能指针,用于保存指针的用户数量并在没有人使用时删除它。
用户回答回答于

你在C#中总是“使用指针”,它只是隐藏起来。

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

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

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

例如,让我们说我们的记忆包含以下值:

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

我们来定义一个变量,x编译器已经选择将这个变量放置在地址2处。可以看出,其值为x1。

现在让我们来定义一个指针,p该编译器选择在地址7.放的价值p4。该值指出,通过p在地址4中的值,也就是值2。获取该值称为解引用

需要注意的一个重要概念是,就内存而言,不存在类型这样的事物:只有字节值。不管你喜欢什么,你都可以选择解释这些字节值。例如,取消引用char指针只会得到1个字节表示一个ASCII码,但解引用一个int指针可能会得到4个字节组成一个32位值。

再看一个例子,你可以使用下面的代码在C中创建一个字符串:

char *str = "hello, world!";

所做的就是说以下几点:

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

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

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

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

如果你最终超过了字符串的末尾,就没有告诉你会指向什么; 但是您的程序仍然会尽职尽责地将其解释为一个字符,即使该值实际上应该表示为一个整数。您可能会试图访问未分配给您的程序的内存,然后您的程序将被操作系统终止。

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

array[5]

完全等同于

*(array + 5)

扫码关注云+社区

领取腾讯云代金券