在C,我们不能用&找出一个寄存器变量的地址,但在C ++中,我们可以这样做。 为什么是合法的C ++,但不是在C? 有人可以请解释深入这个概念。
Answer 1:
下面是从第6.7.1(脚注101)的摘录C99标准(PDF) :
实现可以将任何
register
简单地声明为auto
申报。 然而, 可寻址的存储是否被实际使用时,对象的任何部分的地址与存储类说明寄存器声明不能计算 ,明确地(通过使用一元的&
操作者如在6.5.3.2所讨论的)或隐含地(由阵列名称转换为如在6.3.2.1所讨论的指针)。 因此,可被应用于阵列的唯一操作者申报与存储类说明register
被sizeof
。
和从第7.1.1节所述的第3段C ++标准(PDF) :
一个
register
说明符具有相同的语义的auto
与一个提示,如此声明的对象将被频繁使用的执行一起符。 [注:提示可以忽略不计,而且在大多数的实现,如果对象的地址是它会被忽略。 末端注]
约趣味花絮register
C ++的组(WG21) 想要贬低register
:
该
register
关键字提供很少的功能,提供不亚于一记说的是通常被忽略了一丝。 它应该在这个版本的标准被弃用,释放保留的名称弥补了未来的标准使用,就像auto
已经重新使用这阵子为是同样无用。从2009年3月会议记录:
该CWG的共识是赞成自嘲的
register
。
看一下C99组(WG14) 约说register
(PDF)在一次会议上:
普遍同意弃用“
auto
”的关键字。 我们应该问WG21回到以前的使用“的register
”(无地址)? 不,这不会与WG21飞。
Answer 2:
寄存器关键字只是一个提示,可以忽略。 大多数C ++编译器忽略它所有的时间,但任何C ++编译器会忽略它,如果你把变量的地址,或者创建一个参考吧。
在另一方面,C ++编译器并没有忽视“注册”只是因为你采取的变量的地址。 从理论上讲,编译器可以将其存储在寄存器中,给你以某种方式映射到幕后的寄存器一些神奇的指针值,但是这将是非常小的收益了很多的工作,所以没有编译器(据我所知)做这样的事情。
由于寄存器是可忽略的用C,以及,我怀疑,不要采取寄存器变量的地址明确的禁令只是从检查这个负担减轻的C编译器。
C ++标准的相关部分是7.1.1.3:
寄存器说明符具有相同的语义与一个提示,如此声明的对象将被频繁使用的执行一起自动符。 [注:提示可以忽略不计,而且在大多数的实现,如果对象的地址是它会被忽略。 末端注]
Answer 3:
很抱歉的答案超级晚。
问题是,在C, register
在寄存器这就是为什么只有最初的意思是存储价值int
和char
可用于它。 但随着时间的推移,尤其是标准C ++,它扩大到“快速访问”,而不是“在CPU的寄存器”。 因此,在C ++中,数组也许是register
类型,但是我们知道这是不可能的存储阵列的CPU寄存器。 因此,它在逻辑上是好,以解决C ++寄存器(在上述意义上的),但是仍然会毫无意义,如果值实际上在一个CPU寄存器。
Answer 4:
我认为关键字根本不会把它做成的语言,如果不是因为C兼容性。 虽然我不能和任何说的,如果是这样的话,在我看来,还有它是合法的超过实际的原因仅仅是一个标准的强制执行的“编译器比你更聪明”的条款:C ++需要的东西地址不允许更容易地比C一样。 具体做法是:成员函数,以及引用。
由于成员函数需要一个隐含的this
参数,就不可能从一个声明的对象称他们register
。 在C,有什么说从禁止你register struct X x;
,所以这样的语言必须在C被允许++ [自C-兼容性是整个原因关键字甚至存在。 但是,如果你禁止调用成员函数以及采取的地址,也涵盖了最初的构造函数调用。 从本质上讲,它不会对非POD类型的工作。 所以,你最终用一个存储类说明这是仅适用于法律的类型,当所有其他部分可以用于任何的一小部分。
您也无法创建此类对象的引用,尽管从技术上讲,编译器不具有治疗作为指针引用。 register int i; int& x;
不要求有空间的两个变量,但如果你以后做&x
你结束了一个指向i
。 因此,最初的结构必须被渲染非法的。 虽然这似乎是一个非问题,因为用C不存在引用无论如何,回到我们之前的点,与申报POD类型register
说明符不能再被复制。 所述编译器提供复制构造的形式为X::X(const X&)
或X::X(X&)
适当。
因此,为了维持与C兼容,他们必须做出register
在它并不适用于所有类型的存储类说明独特的,修改标准的至少两个不同的部分别处[指定你不能创建与声明引用变量register
说明符,并以某种方式解决了POD复制]的引用。 或者,他们可能只是说:“它的好采取地址”,让编译器决定是否要兑现的要求。 东西他们打算无论如何做。
Answer 5:
寄存器变量没有地址,它的举行(至少它应该举行)的CPU寄存器。 由于寄存器修改不过是一个提示,如果强制编译器生成代码以提取它的地址,修改将被忽略,你会保存在内存中一个常规变量结束。
要直接回答你的问题,哪一个让你把一个寄存器变量的地址(你原来的职位是自相矛盾..)可以让你忽略了自己的暗示,至少应发出警告。 IMO正确的实施方法是禁止服用寄存器变量的地址。
Answer 6:
要记住的重要一点是,“登记”只是一个暗示,编译器(在一个毫无意义的一个;我从来没有见过任何的速度提高,并且大多数编译器可能只是忽略它)。 C和C ++都允许忽略你的“意见”,并保持该变量在内存中。 当然,如果你把变量的地址,它会迫使它分配内存中一个点。
C和C ++只是对你可以做什么,因为他们有不同的语言不同的规则。 C ++的设计者决定让你得到一个寄存器变量,因为它没有伤害任何东西的地址; C不会允许你这样做,因为这将迫使它到内存中。
更多关于它的思考,C的限制可能是该变量必须在块的编译器开始被宣布为它遇到他们,而不考虑它如何以后使用的功能,可以布局变量的存储一样的道理。
Answer 7:
这仅仅是一个受过教育的猜测,但我怀疑,你可以采取一个寄存器的地址在C ++中,因为这样的人认为根本不存在。 C ++可能没有你的具体情况使用寄存器。 请注意,存储类限定符register
只是一个提示编译器(和大多数如果不是所有现代的编译器高兴地完全忽略它)。
Answer 8:
C和C ++是两种不同的语言,有一个大的共同子集。 这就是为什么有些事情是它们之间的不同。
虽然我不明白你的问题, register
是(至少在C ++)一个暗示,一个变量可能会更频繁地访问,仅此而已。 在C,这意味着你不能用走的地址&
一元运算符,这在当时取得了一定的意义。 在C的初期,预计该编译器可能不打扰为变量分配内存,所以不一定会地址服用。
(计算机通常有寄存器,这是CPU的快速访问的部分,因此最快的存储访问。一个变量可能生活在一个寄存器中,而不是在内存中,如果导致更好的性能。)
现在,几乎所有的编译器足够成熟的做自己的分配不是程序员可以更好,所以使用register
几乎总是毫无意义。