在 C 中,我们不能使用 & 来查找寄存器变量的地址,但在 C++ 中我们可以做同样的事情。为什么它在 C++ 中合法但在 C 中不合法?有人可以深入解释这个概念吗?

有帮助吗?

解决方案

以下是 6.7.1 节(脚注 101)的摘录 C99 标准 (pdf):

该实现可以处理任何 register 声明简单地作为 auto 宣言。然而, 无论是否实际使用可寻址存储,都无法计算使用存储类说明符寄存器声明的对象的任何部分的地址, ,或者显式地(通过使用一元 & 运算符(如 6.5.3.2 中讨论)或隐式(通过将数组名称转换为指针,如 6.3.2.1 中讨论)。因此,唯一可以应用于用存储类说明符声明的数组的运算符 registersizeof.

并从第 7.1.1 节第 3 段 C++ 标准 (pdf):

A register 说明符具有相同的语义 auto 说明符以及对实现的提示,表明如此声明的对象将被大量使用。 [笔记:该提示可以被忽略,并且在大多数实现中,如果获取了对象的地址,则该提示将被忽略。——尾注]

关于的有趣花絮 register

C++ 组 (WG21) 想要弃用 register:

register 关键字的作用非常小,仅提供注释中通常会被忽略的提示。在这个版本的标准中应该弃用它,释放保留名称以供未来标准使用,就像 auto 这次由于同样无用而被重新使用。

2009 年 3 月会议记录:

CWG 一致同意弃用 register.

看看C99组(WG14)是什么 说关于 register (pdf) 在一次会议上:

普遍同意废除“auto” 关键字。我们是否应该要求WG21回到先前的使用“register“(没有地址)?不,这不能与 WG21 一起飞行。

其他提示

在寄存器关键字只是一个提示,可以忽略。大多数C ++编译器忽略它所有的时间,但任何C ++编译器会忽略它,如果你把变量的地址,或者创建一个参考吧。

在另一方面,一个C ++编译器不的的忽视“注册”只是因为你采取的变量的地址。从理论上讲,编译器可以将其存储在寄存器中,给你以某种方式映射到幕后的寄存器一些神奇的指针值,但是这将是非常小的收益了很多的工作,所以没有编译器(据我所知)的确这样的事情。

由于寄存器是可忽略的用C为好,我怀疑对服用寄存器变量的地址明确取缔是简单地从检查此的负担减轻C编译器。

C ++标准的相关部分是7.1.1.3:

  

一个寄存器指定具有相同的语义的自动带一个提示,如此声明的对象将被频繁使用的执行一起说明符。 [注:提示可以忽略不计,而且在大多数的实现,如果对象的地址是它会被忽略。末端纸币]

很抱歉的答案超级晚。

的问题是,在C,register原意在寄存器这就是为什么仅intchar可以用于其存储的值。但随着时间的推移,尤其是标准C ++,它扩大到“快速访问”,而不是“在CPU的寄存器”。 因此,在C ++中,数组也许register类型,但是我们知道这是不可能的存储阵列的CPU寄存器。因此,它在逻辑上是好,以解决C ++寄存器(在上述意义上的),但是仍然会毫无意义,如果值实际上在一个CPU寄存器。

我假定关键词不会还送入语言,如果它不是为C兼容性。虽然我不能和任何说的,如果是这样的话,在我看来,还有它是合法的超过实际的原因仅仅是一个标准的强制执行的“编译器比你更聪明”的条款:C ++需要的东西地址不允许更容易地比C一样。具体做法是:成员函数,以及引用。

由于成员函数需要一个隐式this参数,这将是不可能从一个对象调用它们宣称register。在C,有什么说从禁止register struct X x;你,所以这样的语言会在C到允许++ [因为C-兼容性的全部理由关键字甚至存在。但是,如果你禁止调用成员函数以及采取的地址,也涵盖了最初的构造函数调用。从本质上讲,它不会对非POD类型的工作。所以,你最终用一个存储类说明这是仅适用于法律的类型,当所有其他部分可以用于任何的一小部分。

您还不能创建这样的对象的引用,尽管从技术上讲,编译器不具有治疗作为指针引用。 register int i; int& x;不要求有空间的两个变量,但如果你以后做&x你结束了一个指向i。因此,最初的结构必须被渲染非法的。虽然这似乎是一个非问题,因为用C不存在引用无论如何,回到我们之前的点,与register说明符声明POD类型不能再被复制。编译器提供的拷贝构造形式X::X(const X&)X::X(X&)适当的。

所以,为了保持C兼容性,他们必须做出register独一无二的,因为,它并不适用于所有类型的存储类说明,并修改了标准的至少两个不同的部分别处[指定,你可以不创建与register符声明的变量的引用,并以某种方式解决了参考POD复制。或者,他们可能只是说:“它的好采取地址”,让编译器决定是否要兑现的要求。东西他们打算无论如何做。

一个寄存器变量不具有一个地址,它是保持(至少它应该被保持)在一个CPU寄存器。由于寄存器修改不过是一个提示,如果强制编译器生成代码以提取它的地址,修改将被忽略,你会保存在内存中一个常规变量结束。

要直接回答你的问题,哪一个让你把一个寄存器变量的地址(你原来的职位是自相矛盾..)可以让你忽略了自己的暗示,至少应发出警告。 IMO的正确实施。将不允许服用寄存器变量的地址。

要记住的重要一点是,“登记”只是一个暗示,编译器(在一个毫无意义的一个;我从来没有见过任何的速度提高,并且大多数编译器可能只是忽略它)。 C和C ++都允许忽略你的“意见”,并保持该变量在内存中。当然,如果你把变量的地址,这将迫使它分配内存中一个点。

C和C ++只是对你可以做什么,因为他们有不同的语言不同的规则。 C ++的设计者决定让你得到一个寄存器变量,因为它没有伤害任何东西的地址; C不会允许你这样做,因为这将迫使它到内存中。

思考有关它的更多,C的限制可能是出于同样的原因的变量必须在块的编译器开始被宣布为它遇到他们,而不考虑它如何在后面用能布局变量的存储的功能。

这是唯一一个受过教育的猜测,但我怀疑,你可以采取一个寄存器的地址在C ++中,因为这样的人认为根本不存在。 C ++可能没有你的具体情况使用寄存器。请注意,存储类限定符register只是一个提示给编译器(和大多数如果不是所有现代编译器愉快地完全忽略它)。

C和C ++有两种不同的语言,具有大的公共子集。这就是为什么有些事情是它们之间的不同。

虽然我不明白你的问题,register是(至少在C ++)一个暗示,一个变量可能会更频繁地访问,仅此而已。在C,这意味着你不能与&元运算符,这在当时取得了一定的意义上的地址。在C的初期,预期的是,编译器可能不会打扰分配存储器的变量,所以不一定是采取的地址。

(电脑通常具有的寄存器,这是CPU的快速访问的部分,且因此最快的存储访问。一种可变可以生活在一个寄存器中,而不是在存储器中,如果导致更好的性能。)

现在,几乎所有的编译器都足够成熟,做自己的分配比程序员就可以了,所以用register几乎都是没有意义的。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top