据我所知,引用/指针别名会阻碍编译器生成优化代码的能力,因为它们必须确保在两个引用/指针确实是别名的情况下,生成的二进制文件的行为正确。例如,在以下C代码中,
void adds(int *a, int *b) {
*a += *b;
*a += *b;
}
Run Code Online (Sandbox Code Playgroud)
当clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)用-O3标志编译时,它发出
0000000000000000 <adds>:
0: 8b 07 mov (%rdi),%eax
2: 03 06 add (%rsi),%eax
4: 89 07 mov %eax,(%rdi) # The first time
6: 03 06 add (%rsi),%eax
8: 89 07 mov %eax,(%rdi) # The second time
a: c3 retq
Run Code Online (Sandbox Code Playgroud)
下面的代码存回(%rdi)两次的情况下,int *a和int *b别名。
当我们明确告诉编译器这两个指针不能使用restrict关键字别名时:
void adds(int * restrict a, int * restrict …Run Code Online (Sandbox Code Playgroud) 根据文档,
\n\n\n数据竞争会导致未定义的行为,并且当您\xe2\x80\x99尝试在运行时追踪它们时,可能很难诊断和修复;Rust 通过拒绝编译带有数据竞争的代码来防止这个问题!
\n
除非你\xe2\x80\x99re多线程,否则为什么这是一个问题?如果同时访问一个变量及其一个mut引用,\xe2\x80\x99t 这个问题是否仍然存在?
该锈书大约有多个读者和多个可变对象引用的数据竞争情况,可能会导致问题进行会谈。
例如,这段代码:
fn main() {
let mut x = 1;
let r1 = &mut x;
*r1 = 2;
let r2 = &mut x;
*r2 = 3;
println!("{}", r1);
println!("{}", r2);
}
Run Code Online (Sandbox Code Playgroud)
将被 Rust 编译器拒绝,因为r1和r2作用域交织在一起。
但是这里有什么问题呢?我的意思是,这只是一个线程,没有“同时读取和写入”,因此所有这些语句都应严格按顺序执行并给出确定性的可重现结果。