尽管行为的定义是正确的,但编译器可以按照您的意思“优化const” 并不是正确的。
也就是说,编译器不容许假设,仅仅因为一个参数是const T* ptr
,内存指向ptr
不会通过另一个指针被改变。指针甚至不必相等。这const
是一种义务,而不是保证-您(=函数)的一项义务是不要通过该指针进行更改。
为了真正获得保证,您需要使用restrict
关键字标记指针。因此,如果您编译这两个函数:
int foo(const int* x, int* y) {
int result = *x;
(*y)++;
return result + *x;
}
int bar(const int* x, int* restrict y) {
int result = *x;
(*y)++;
return result + *x;
}
该foo()
函数必须从中读取两次x
,而bar()
只需要读取一次:
foo:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, DWORD PTR [rdi] # second read
ret
bar:
mov eax, DWORD PTR [rdi]
add DWORD PTR [rsi], 1
add eax, eax # no second read
ret
看到这个直播GodBolt。
restrict
只是C中的关键字(自C99起);不幸的是,到目前为止,尚未将其引入C ++(由于可怜的原因,将其引入C ++更为复杂)。但是,许多编译器确实支持它__restrict
。
底线:编译器在编译时必须支持您的“神秘”用例f()
,并且不会有任何问题。
有关的用例,请参阅此帖子restrict
。
const
不是“您(=函数)没有通过该指针进行更改的义务”。C标准允许该函数const
通过强制转换删除,然后通过结果修改对象。本质上,const
这只是建议性的提示,为程序员提供了便利,可以帮助避免意外修改对象。