Rust 是不是要变异&;在不安全的铁锈中通过一个*多个? 设r=42; 不安全{ 设p=&r为*const i32为*mut i32; *p+=1; } 普林顿!(“{}”,r);
上述代码是否为UB?是否有可能Rust 是不是要变异&;在不安全的铁锈中通过一个*多个? 设r=42; 不安全{ 设p=&r为*const i32为*mut i32; *p+=1; } 普林顿!(“{}”,r);,rust,Rust,上述代码是否为UB?是否有可能rustc(假设r是&i32)以一种最终成为UB的方式对其进行优化 这个怎么样↓ 让rc=rc::new(42); 不安全{ 设p=&*rc as*const i32 as*mut i32; *p+=1; } 普林顿!(“{}”,rc); Rc是一个引用计数指针,因此它不是线程安全的。 假设以上是在一个线程中执行的,它是否会以UB结束?这两种情况都肯定是UB 这里的主要问题是,除了UnsafeCell内部值之外,对共享引用后面的值所做的任何更改都是非法的。编译器
rustc
(假设r
是&i32
)以一种最终成为UB
的方式对其进行优化
这个怎么样↓
让rc=rc::new(42);
不安全{
设p=&*rc as*const i32 as*mut i32;
*p+=1;
}
普林顿!(“{}”,rc);
Rc是一个引用计数指针,因此它不是线程安全的。假设以上是在一个线程中执行的,它是否会以
UB
结束?这两种情况都肯定是UB
这里的主要问题是,除了UnsafeCell
内部值之外,对共享引用后面的值所做的任何更改都是非法的。编译器可以轻松地优化第一种情况下的更改,只需将r
替换为println
调用
第二种情况有点棘手,但它基于相同的事实。注意,表达式和*r
,其中r
为Rc
类型,为&T()类型:
使用std::rc::rc;
fn试验(r:Rc){
let U3;:()=&*r;//错误:预期为(),发现为&T
}
诀窍在于Rc
derefs到T
,因此*r
具有类型T
因此,它还是被视为可变的不可变引用 这两种情况都是肯定的 这里的主要问题是,除了
UnsafeCell
内部值之外,对共享引用后面的值所做的任何更改都是非法的。编译器可以轻松地优化第一种情况下的更改,只需将r
替换为println
调用
第二种情况有点棘手,但它基于相同的事实。注意,表达式和*r
,其中r
为Rc
类型,为&T()类型:
使用std::rc::rc;
fn试验(r:Rc){
let U3;:()=&*r;//错误:预期为(),发现为&T
}
诀窍在于Rc
derefs到T
,因此*r
具有类型T
因此,它还是被视为可变的不可变引用 不,编译器将无法将
r
内联到println调用中,原因很简单,因为我们以后使用了指向r
的指针。“用作可变的不可变引用”是非法的,但不是必需的。想想RefCell是如何实现的?基本上将不可变内存视为可变内存。RefCell在内部使用UnsafeCell。请参阅:“我们有一个指向r的指针,稍后使用”-但我们只能将其用于读取(从编译器的角度来看),因为同时我们还有一个不可变的引用处于活动状态。不,编译器将无法将r
内联到println调用中,这仅仅是因为我们有一个指向r
的指针,稍后使用。“不可变引用用作可变引用”是非法的,但不是必须的。想想RefCell是如何实现的?基本上将不可变内存视为可变内存。RefCell在内部使用UnsafeCell。请参阅:“我们有一个指向r的指针,稍后使用”-但我们只能将其用于读取(从编译器的角度来看),因为同时我们还有一个不可变的引用处于活动状态。
use std::rc::Rc;
fn test<T>(r: Rc<T>) {
let _: () = &*r; // error: expected (), found &T
}