ayu*_*hgp 44 c c++ language-lawyer c++11
在阅读Herb Sutter撰写的关键词(或其他名称)时,我遇到了以下几点:
没错,有些关键字在语义上等同于空格,这是一个美化的评论.
和
我们已经看到为什么C++语言将关键字视为保留字,我们已经看到两个关键字-auto和register--它们对C++程序没有任何语义差异.不要使用它们; 无论如何,它们只是空格,并且有更快的方式来输入空格.
如果关键字auto
(可能不是在C++ 11中)并且register
没有价值,那么它们为什么被创建和使用?
如果包含register
变量之前没有任何区别
#include<stdio.h>
int main(){
register int a = 15;
printf("%d\n%d\n",&a,a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
为什么上述程序会出错?
test_register.c:在函数'main'中:
test_register.c:4:2:错误:请求的寄存器变量'a'的地址
的printf( "%d \n%d \n",&A,A);
以下程序适用于C++.
#include<iostream>
int main(){
register int a = 15;
std::cout<<&a<<'\n'<<a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
The*_*kis 54
在C中,register
存储类用作编译器的提示,以表示变量应优先存储在寄存器中.请注意,将register
变量存储在实际寄存器中的提示可能会或可能不会受到尊重,但在任何一种情况下,相关限制仍然适用.见C11,6.7.1p6(强调我的):
具有存储类说明符的对象的标识符声明
register
表明对对象的访问尽可能快.这些建议有效的程度是实施定义的.[脚注121][脚注121]实施可将任何
register
声明简称为auto
声明.但是,无论是否实际使用了可寻址存储,使用存储类说明符声明的对象的任何部分的地址register
都无法显式(通过使用6.5.3.2中讨论的一元和运算符)或隐式(通过将数组名称转换为指针,如6.3.2.1中所述.因此,可以应用于使用存储类说明符声明的数组的唯一运算符register
是sizeof
和_Alignof
.
在C++中,它只是一个未使用的保留关键字,但可以合理地假设它保留了与C代码的语法兼容性.
在C中,auto
存储类定义了自动存储的变量,但由于默认情况下函数局部变量auto
,因此通常不会使用它.
类似地,假设它最初只是为了语法兼容性而被转移到C++是合理的,尽管后来它有了自己的含义(类型推断).
Tav*_*nes 26
register
在C中有两个目的:
这类似于const
,
作为一个例子,考虑这个简单的功能:
int sum(const int *values, size_t length) {
register int acc = 0;
for (size_t i = 0; i < length; ++i) {
acc += values[i];
}
return acc;
}
Run Code Online (Sandbox Code Playgroud)
程序员编写register
了将累加器保持在堆栈之外的状态,避免每次更新时写入内存.如果实现变为这样的事情:
// Defined in some other translation unit
void add(int *dest, int src);
int sum(const int *values, size_t length) {
register int acc = 0;
for (size_t i = 0; i < length; ++i) {
add(&acc, values[i]);
}
return acc;
}
Run Code Online (Sandbox Code Playgroud)
acc
当其地址用于add()
调用时,该变量不能再存储在寄存器中,因为寄存器没有地址.因此编译器将标记&acc
为错误,让您知道您可能通过阻止acc
生成寄存器来破坏代码的性能.
在早期编译器是笨重的,并且变量将存在于整个功能的单个位置时,这曾经变得更加重要.现在,变量可以将大部分时间用在寄存器中,只有在其地址被移动时才暂时移动到堆栈中.也就是说,这段代码:
/* Passed by reference for some reason. */
void debug(const int *value);
int sum(const int *values, size_t length) {
int acc = 0;
for (size_t i = 0; i < length; ++i) {
acc += values[i];
}
debug(&acc);
return acc;
}
Run Code Online (Sandbox Code Playgroud)
会导致acc
在旧编译器中的整个函数的堆栈上生存.现代编译器将保留acc
在寄存器中,直到debug()
呼叫之前.
现代C代码通常不使用register
关键字.
Yu *_*Hao 10
C99 Rationale提供了更多关键字上下文register
:
国际标准的基本原理 - 编程语言 - C.
§6.7.1存储类说明符
由于
register
无法获取变量的地址,因此存储类的对象register
实际上存在于与其他对象不同的空间中.(函数占用了第三个地址空间.)这使它们成为最佳放置的候选者,这是声明寄存器的通常原因; 但它也使它们成为更积极优化的候选者.
归档时间: |
|
查看次数: |
7265 次 |
最近记录: |