restrict是C99标准引入的指针限定符,用于向编译器承诺该指针是访问其所指向内存的唯一途径,从而消除指针别名歧义、启用激进优化(如指令重排、冗余访存消除);C++标准不支持restrict,但GCC/Clang提供__restrict__扩展实现等效功能。

restrict 不是 C++ 标准关键字,C++ 语言本身不支持 restrict。你在 C++ 代码里写 int* restrict ptr,标准编译器(如 clang++ 或 g++ 默认模式)会直接报错或忽略该关键字。
C++ 中怎么写等效的 restrict?
GCC 和 Clang 提供了兼容性扩展:__restrict__(双下划线)或 __restrict(单下划线),它们在 C++ 模式下可用,语义与 C99 的 restrict 一致。
常见写法包括:
void process(float* __restrict__ a, float* __restrict__ b, int n)float* __restrict__ ptr = new float[1024];- 数组参数本质是指针,所以
void f(int arr[__restrict__])是非法语法;必须写成指针形式,例如void f(int* __restrict__ arr, int n)
为什么加 __restrict__ 能提升性能?
核心是消除指针别名歧义。比如这个函数:
立即学习“C++免费学习笔记(深入)”;
void add_arrays(int* __restrict__ a, int* __restrict__ b, int* __restrict__ c, int n) {
for (int i = 0; i < n; ++i) {
a[i] = b[i] + c[i];
}
}没有 __restrict__ 时,编译器必须假设 a、b、c 可能重叠(例如 add_arrays(x, x+1, x+2, 10)),因此每次循环都得重新从内存读取 b[i] 和 c[i],无法安全地向量化或展开循环。
加上 __restrict__ 后,编译器确认三者内存互不重叠,可:
- 把多个迭代合并为一次 SIMD 指令(如用 AVX 一次处理 8 个
int) - 将
b[i]和c[i]值缓存在寄存器中,避免重复加载 - 更激进地重排指令顺序,隐藏访存延迟
容易踩的坑
违反 __restrict__ 承诺会导致未定义行为(UB),且编译器通常不检查:
- 传入重叠地址:比如
add_arrays(arr, arr, arr, 10)—— 这是明确违反约定 - 用其他指针修改同一块内存:
int* __restrict__ p = buf; int* q = buf; *q = 42;—— UB - 混用
malloc返回值和全局数组指针,却都标__restrict__,但实际指向同一区域 - 在模板函数中泛化使用
__restrict__,但调用方无法保证别名约束
这类错误往往在高优化等级(-O2 或 -O3)下才暴露,表现为计算结果错乱、崩溃或静默数据损坏,调试难度极高。
真正关键的不是“能不能加”,而是“你能否在所有调用路径上 100% 保证无别名”。一旦不确定,宁可不加 —— 宁可慢一点,也不能 UB。


















