我想重新解释对可变引用的不可变引用(在不安全的块中),并独自负责安全检查,但看来我无法使用mem::transmute()
来这样做。
let map_of_vecs: HashMap<usize, Vec<_>> = ...;
let vec = map_of_vecs[2];
/// obtain a mutable reference to vec here
Vec
包裹到Cell
中,因为这会影响使用map_of_vecs
的所有其他代码区域,而我只需要一行即可。 li>
map_of_vecs
的可变访问权限答案 0 :(得分:5)
Rust优化器假设&mut T
引用是唯一的。例如,它可能推断出可以重用特定的内存,因为存在对该内存的可变引用,但是再也不会对其进行访问。
但是,如果将&T
转换为&mut T
,则可以为同一数据创建多个可变引用。如果编译器做出此假设,您最终可能会取消引用已经被其他内容覆盖的值。
这只是编译器可能如何利用可变引用是唯一的假设的一个示例。实际上,编译器可以自由使用它认为合适的任何方式使用此信息-可能(并且可能会)在版本之间进行更改。
即使您认为,您也已保证引用没有别名,您也无法始终保证代码的用户不会创建更多引用。即使您认为可以肯定,引用的存在也非常微妙,很容易错过一个引用。例如,当您调用采用&self
的方法时,这就是引用。
答案 1 :(得分:2)
Rust编译器使用LLVM &T
和noalias
属性注释readonly
函数参数(前提是T
不包含任何UnsafeCell
部分)。 noalias
属性告诉LLVM,该指针后面的内存只能通过 this 指针写入(而不能通过任何其他指针),而readonly
属性告诉LLVM它不能通过此指针(但可能是其他指针)写入。结合使用,这两个属性允许LLVM优化器假定在执行此功能期间内存完全没有变化,并且可以基于此假设来优化代码。优化程序可能会重新排序指令或删除代码,只有在您确实遵守此合同的情况下,这种方法才可以安全地进行。
该转换可能导致未定义行为的另一种方法是针对静态变量:没有UnsafeCell
的不可变静态变量将被放置到只读存储器中,因此,如果您实际写入它们,则代码将出现段错误。
对于具有UnsafeCell
的参数,编译器不会发出readonly
属性,并且将包含UnsafeCell
的静态变量放入可写内存。