在 C 语言中,我们无法使用 & 来获取寄存器变量的地址,但在 C++ 中可以这样做。为什么在 C++ 中合法而在 C 中不行呢?可以有人详细解释一下这个概念吗?
在 C 语言中,我们无法使用 & 来获取寄存器变量的地址,但在 C++ 中可以这样做。为什么在 C++ 中合法而在 C 中不行呢?可以有人详细解释一下这个概念吗?
register
声明简单地视为auto
声明。但是,无论是否实际使用可寻址存储器,都不能计算用存储类说明符register
声明的对象的任何部分的地址,无论是显式地(如6.5.3.2中所讨论的使用一元&
运算符)还是隐式地(通过将数组名称转换为指针,如6.3.2.1中所讨论的)。因此,可以应用于使用存储类说明符register
声明的数组的唯一运算符是sizeof
。register
说明符具有与auto
说明符相同的语义,并提示实现声明的对象将被大量使用。[注意:如果取了对象的地址,则提示可以被忽略,在大多数实现中,如果取了对象的地址,则会被忽略。-end note]
register
的有趣细节
C++组(WG21)希望弃用register
关键字:
register
关键字几乎没有什么作用,只提供了一个提示,通常被忽略。它应该在这个标准的版本中被弃用,为未来标准释放保留的名称,就像auto
一样在此次使用中也被重新使用,因为它同样无用。来自2009年3月会议的笔记:
CWG的共识是支持弃用
register
。
看看C99组(WG14)在会议上对register
说了什么(pdf):
普遍同意弃用“
auto
”关键字。我们是否应该要求WG21回到以前的“register
”使用方式(没有地址)?不,这对WG21来说行不通。
非常抱歉回答晚了。
问题在于,在C语言中,register
原本的意思是将值存储在寄存器中,这就是为什么只有 int
和 char
可以用它来声明。但随着时间的推移,特别是在标准C++中,它的含义扩大到了“快速访问”而不是“CPU寄存器中的存储”。
因此,在C++中,数组可能是一个register
类型,但我们知道不可能将数组存储在CPU寄存器中。因此,逻辑上来说,可以使用C++寄存器(以上所述的意义),但如果实际值在CPU寄存器中,则仍然没有意义。
register说明符与auto说明符具有相同的语义,并提示实现,声明的对象将被频繁使用。[注意:如果获取对象的地址,则提示可能被忽略,在大多数实现中,如果获取对象的地址,则它将被忽略。-注释]
由于成员函数需要隐式的 this
参数,所以无法从声明为 register
的对象调用它们。在C中,没有任何限制你可以说 register struct X x;
, 因此在C++中必须允许这种语言。但是如果禁止调用成员函数以及获取地址,那么也就涵盖了初始构造函数调用。本质上,它不适用于非POD类型。因此,您最终得到了一种存储类说明符,它仅适用于一小部分合法类型,而其他所有类型都可以用于任何类型。
您还不能创建指向这些对象的引用,即使从技术上讲,编译器不必将引用视为指针。不需要为两个变量腾出空间,但如果稍后执行 &x
,则会得到指向 i
的指针。因此,初始构造必须被禁止。虽然这似乎不是问题,因为引用在C中不存在,但回到我们之前的观点,使用 register
说明符声明的POD类型不再能够被复制。编译器提供的复制构造函数为 X::X(const X&)
或 X::X(X&)
。
因此,为了保持与C的兼容性,他们必须使 register
成为一个唯一的存储类说明符,因为它不适用于所有类型,并修改标准的至少两个不同部分(以指定不能创建带有 register
说明符的变量的引用,并解决POD复制的引用)问题)。或者,他们可以只是说“获取地址没关系”,并让编译器决定是否遵守请求。他们本来就打算这样做。
一个寄存器变量没有地址,它(至少应该)保存在CPU寄存器中。由于寄存器修饰符只是一个提示,如果你强制编译器生成提取其地址的代码,修饰符将被忽略,你最终会得到一个保存在内存中的常规变量。
直接回答你的问题,任何允许你获取寄存器变量地址的方式(你原始帖子中有自相矛盾的地方...)都会忽略你的提示,并且至少会发出一个警告。我个人认为正确的实现应该是不允许获取寄存器变量的地址。
register
?在问题的背景下,最好注意它们之间的区别。 - CB BaileyC和C++是两种不同的语言,但有很大的共同子集。这就是为什么它们之间有些东西是不同的。
虽然我不理解你的问题,但register
(至少在C++中)是一个提示,表明变量可能更频繁地被访问,仅此而已。在C中,它意味着您不能使用&
一元运算符获取地址,这在当时是有一定道理的。在C的早期,编译器可能不会为变量分配内存,因此可能没有地址可用。
(计算机通常具有寄存器,这是CPU的快速访问部分,因此是最快的存储器。如果将变量放在寄存器中而不是内存中,则可能会获得更好的性能。)
现在,几乎所有的编译器都足够复杂,可以比程序员更好地进行自己的分配,因此使用register
几乎总是没有意义的。
register
只是对编译器的提示(如果不是所有现代编译器都会完全忽略它)。