在 C++ 中,名称实际上是底层的指针吗?例如:
// num is a name that points to the address of the
// memory location containing 32.53
double num (32.53);
*num; // so can we deference it and get 32.53?
num; // same as *num but the compiler automatically
// dereferences the name for us?
Run Code Online (Sandbox Code Playgroud)
这个问题有点奇怪,混合了“机器层面发生了什么?” 以及关于指针的 C++ 语言语义。因此,我可以明白为什么答案是是/否。“是”,因为在语言语义之外,标识符可以被认为是指内存中的位置;和“否”,因为它仍然不是 C++ 指针,并且引用代码中所示的非指针双精度是不正确的。
所以我认为两个阵营都成功地回答了我的问题。也许可以将其重述为:“既然名称引用内存位置,为什么不能将它们视为隐式指针?” 但这样的问题可能会引发模糊的争论,或者根本不值得回答。我会仔细检查答案,并尝试找到(我认为)从两个角度都能最好地回答问题的答案。换句话说,它不只是说“这不是 C++ 指针虚拟!” 或“当然这个名字以某种方式指向记忆”。
如果将指针的定义扩展到“引用内存中某些信息的任何概念设备”,那么,是的,绝对如此。
然而,没有人这样做。
如果您使用术语“句柄”,您会更接近金钱,该术语在源代码中被用来表示“指针”、“引用”、“变量”、“资源对象”、“名称”、“访问器” 、“标识符”以及无数其他东西。
人们通常会得出这样的结论:一般术语过于模糊,最终会坚持使用特定于语言的术语(例如 C++ 的“指针”,其语义非常具体,不包括您提出的那些)或明确的术语并被整个行业广泛接受。这些人很少。
指针是程序员可见的值,它保存某个对象的位置(或者不指向对象的空值,或不确定的值)。
尽管在运行时解析名称引用时涉及到寻址,但变量名称在 C++ 中不是指针。这是因为变量名不是代表位置的运行时值;而是代表位置的运行时值。它们是编译时(对于具有链接的外部名称,链接时)符号,表示位置。
“指针”和“地址”不是同一件事。例如,当我们调用一个函数时,假设它没有尾部调用优化或内联,通常会在某处存储“返回地址”,以便函数可以返回到调用者。该地址不是指针;或者至少不是 C++ 指针。它是一个由实现在幕后管理的“无用户可服务组件”,就像堆栈指针(如果有这样的东西)、堆栈帧指针和其他机器级功能一样。C++ 引用,至少在某些情况下,也是使用运行时地址来实现的。C++ 引用也不是指针。
有一个与变量名关联的运行时指针值,您可以使用取址运算符访问此属性:
double *pnum = #
Run Code Online (Sandbox Code Playgroud)
但不是这样的:
*num; // so can we deference it and get 32.53?
Run Code Online (Sandbox Code Playgroud)
你尝试过吗?一元解引用运算符需要指针类型的表达式;它不适用于类型的表达式double。(如果适当重载,它可以与类类型的表达式一起使用,这是另一回事。)
虽然通过运算符&我们可以获得一个指向名为 的存储位置的指针num,但该名称num本身并不是该指针。
当我们评估类似 的代码时num = 3,很可能涉及地址。或者可能不是。例如,如果num优化到寄存器中,则它只会加载3到该寄存器中。即使num有内存地址,在这种情况下该地址也是程序员不可见的。指针是程序员可见的:程序员创建它们、替换它们、取消引用它们、将它们存储在变量中、将它们传递给函数等等。
事实上,在 C++ 中,名称并不是任何东西;它只是一个名称。名称不需要在运行时保留,并且不能以任何可移植的方式访问。(为了进行符号调试,实现可以在编译后保留有关名称的信息,并且支持动态链接的平台可以从字符串中查找动态符号。)