你如何解释C#/ Java开发人员的C++指针?

Mic*_*eth 17 c# c++ java pointers

我是一名试图学习C++的C#/ Java开发人员.当我尝试学习指针的概念时,我很惊讶以前我必须处理这个概念.如何仅使用.NET或Java开发人员熟悉的概念来解释指针?我是否真的从来没有处理过这个问题,它只是隐藏在我身上,还是我一直都在使用它而不称之为?

Mar*_*ork 17

C++中的Java对象

Java对象相当于C++共享指针.

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

C++对象.

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

  • Static Storage Duration对象.
    • 这些是在启动时(主要之前)创建的,并在主要退出后死亡.
      有一些技术上的警告,但这是基础知识.
  • 自动存储持续时间对象
    • 这些是在超出范围时声明和销毁时创建的.
      我相信这些就像C#结构
  • Dynamic Storage Duration对象

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

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


sjm*_*ett 7

你在C#中一直"使用指针",它只是对你隐藏.

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

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

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

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

Address [0] [1] [2] [3] [4] [5] [6] [7]
Data    5   3   1   8   2   7   9   4
Run Code Online (Sandbox Code Playgroud)

让我们定义一个变量,x编译器选择将变量放在地址2处.可以看出值为x1.

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

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

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

char *str = "hello, world!";
Run Code Online (Sandbox Code Playgroud)

它的作用如下:

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

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

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

int *ptr = get_me_an_int_ptr();
ptr++;
Run Code Online (Sandbox Code Playgroud)

如果你最终走过字符串的末尾,那就不知道你会指出什么; 但是你的程序仍将尽职尽责地将其解释为一个字符,即使该值实际上应该代表一个整数.您可能正在尝试访问未分配给您的程序的内存,并且您的程序将被操作系统杀死.

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

array[5]
Run Code Online (Sandbox Code Playgroud)

完全等同于

*(array + 5)
Run Code Online (Sandbox Code Playgroud)