- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在围绕 C 库编写一个 Rust 包装器,同时我正在尝试利用 The Book 中提到的“可空指针优化” , 但我找不到转换 Option<&T>
的好方法至 *const T
和 Option<&mut T>
至 *mut T
就像他们描述的那样。
我真正想要的是能够调用Some(&foo) as *const _
.不幸的是,这行不通,所以我能想到的下一个最好的事情是 Option<T>
上的特征。这让我可以调用 Some(&foo).as_ptr()
.以下代码是该特征的工作定义和实现:
use std::ptr;
trait AsPtr<T> {
fn as_ptr(&self) -> *const T;
}
impl<'a, T> AsPtr<T> for Option<&'a T> {
fn as_ptr(&self) -> *const T {
match *self {
Some(val) => val as *const _,
None => ptr::null(),
}
}
}
现在我可以调用 Some(&foo).as_ptr()
得到 *const _
, 我希望能够调用 Some(&mut foo).as_ptr()
得到 *mut _
.以下是我为此所做的新特征:
trait AsMutPtr<T> {
fn as_mut_ptr(&self) -> *mut T;
}
impl<'a, T> AsMutPtr<T> for Option<&'a mut T> {
fn as_mut_ptr(&self) -> *mut T {
match *self {
Some(val) => val as *mut _,
None => ptr::null_mut(),
}
}
}
问题是,AsMutPtr
特质不会编译。当我尝试时,出现以下错误:
error[E0507]: cannot move out of borrowed content
--> src/lib.rs:22:15
|
22 | match *self {
| ^^^^^
| |
| cannot move out of borrowed content
| help: consider removing the `*`: `self`
23 | Some(val) => val as *mut _,
| --- data moved here
|
note: move occurs because `val` has type `&mut T`, which does not implement the `Copy` trait
--> src/lib.rs:23:18
|
23 | Some(val) => val as *mut _,
| ^^^
我没有看到导致它失败的两个特征之间发生了什么变化——我不认为添加 mut
会有很大的不同。我尝试添加 ref
,但这只会导致不同的错误,而且我不希望无论如何都需要它。
为什么 AsMutPtr
没有特质工作?
最佳答案
不幸的是,为 &mut T
编写了 trait impl而不是 &T
确实有很大的不同。 &mut T
,而不是 &T
, 不是 Copy
,因此您不能直接从共享引用中提取它:
& &T ---> &T
& &mut T -/-> &mut T
这是很自然的——否则可变引用的别名是可能的,这违反了 Rust 的借用规则。
你可能会问那个外层在哪里&
来自。它实际上来自&self
在as_mut_ptr()
方法。如果您有对某物的不可变引用,即使该某物内部包含可变引用,您也无法使用它们来改变它们背后的数据。这也违反了借用语义。
不幸的是,如果没有不安全,我看不出有什么办法可以做到这一点。你需要有 &mut T
“按值”以便将其转换为 *mut T
,但您无法通过共享引用“按值”获取它。因此,我建议您使用ptr::read()
:
use std::ptr;
impl<'a, T> AsMutPtr<T> for Option<&'a mut T> {
fn as_mut_ptr(&self) -> *mut T {
match *self {
Some(ref val) => unsafe { ptr::read(val) as *mut _ },
None => ptr::null_mut(),
}
}
}
val
这是 & &mut T
因为ref
模式中的限定符,因此 ptr::read(val)
返回 &mut T
, 别名可变引用。我认为如果它立即转换为原始指针并且不泄漏是可以的,但即使结果是原始指针,它仍然意味着您有两个别名可变指针。您应该非常小心地处理它们。
或者,您可以修改 AsMutPtr::as_mut_ptr()
按值(value)消费其目标:
trait AsMutPtr<T> {
fn as_mut_ptr(self) -> *mut T;
}
impl<'a, T> AsMutPtr<T> for Option<&'a mut T> {
fn as_mut_ptr(self) -> *mut T {
match self {
Some(value) => value as *mut T,
None => ptr::null_mut()
}
}
}
但是,在这种情况下 Option<&mut T>
将被 as_mut_ptr()
消耗.这可能不可行,例如,如果 Option<&mut T>
存储在一个结构中。我不太确定是否可以通过 Option<&mut T>
以某种方式手动执行重新借用而不仅仅是 &mut T
(不会自动触发);如果可能,则按值as_mut_ptr()
可能是最好的整体解决方案。
关于pointers - 将 Option<&mut T> 转换为 *mut T,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35885670/
Rust 中 *、&、mut、&mut、ref、ref mut 的用法和区别 在 Rust 中,*、ref、mut、& 和 ref mut 是用于处理引用、解引用和可变性的关
这个问题在这里已经有了答案: How to avoid writing duplicate accessor functions for mutable and immutable referenc
我正在尝试使用指向我的结构的指针调用 pthread_join,以便 C 线程可以将结构填充到我指向它的内存中。 (是的,我知道这是非常不安全的..) pthread_join的函数签名: pub u
这个问题在这里已经有了答案: is it possible to filter on a vector in-place? (4 个答案) Is there a way to drain parts
这个问题在这里已经有了答案: is it possible to filter on a vector in-place? (4 个答案) Is there a way to drain parts
以下代码编译失败,因为 MutRef 不是Copy。无法复制,因为&'a mut i32 不是Copy。有什么方法可以让 MutRef 具有与 &'a mut i32 相似的语义吗? 这样做的动机是能
我想转换数组。 例子: func()-> *mut *mut f32; ... let buffer = func(); for n in 0..48000 { buffer[0][n] =
我想对 &mut [u8] 进行一些操作。 在我的测试代码中我有: #[test] fn test_swap_bytes() { let input: &[u8] = b"abcdef";
首先,我不是在问 &mut 之间有什么区别?和 ref mut本身。 我问是因为我想: let ref mut a = MyStruct 与相同 let a = &mut MyStruct 考虑从函数
这个问题在这里已经有了答案: What's the difference between placing "mut" before a variable name and after the ":"
我正在从书中学习 Rust,并且我正在处理第 8 章末尾的练习,但是关于将单词转换为 Pig Latin 的练习我遇到了困难。我想具体看看我是否可以将 &mut String 传递给一个接受 &mut
这段代码: let mut a2 = 99; let b: *mut i32 = &mut a2; *b = 11; // does not compile , even after unsafe {
我正在尝试了解借用检查器。我有一个带有签名的函数 fn SerializeChar(&mut self, value: &mut u8) 我想从 u8 和 i8 获取数据,因为我不关心符号: let
在下面的示例中,t1 编译但 t2 不编译。 &mut &stream有什么特别之处吗?我认为 Deref 不会起作用。 use std::net::TcpStream; fn t1() {
我正在围绕 C 库编写一个 Rust 包装器,同时我正在尝试利用 The Book 中提到的“可空指针优化” , 但我找不到转换 Option 的好方法至 *const T和 Option至 *mut
我试图在 Rust 中实现一个链表,但我在理解这两个函数之间的区别时遇到了一些困难: enum List { Nil, Cons(T, Box>) } fn foo(list: &mu
根据文档,ManuallyDrop是一个零成本包装器。这是否意味着我可以取消引用指向 ManuallyDrop 的原始指针从原始指针转换为 T ? 最佳答案 ManuallyDrop 是 declar
我一直在尝试用 Rust 编写 Redis 模块。这是我第一次尝试使用 Rust FFI 和绑定(bind)。如何在不破坏 Redis 指针的情况下调用此方法并在 Rust 中得到一个数据值? ext
我很难理解以下代码为何具有2种不同的行为: pub fn get(&self, idx: usize) -> &T { let arr = unsafe { core::slice::from
在 documentation为 Unwindsafe我们有: Types such as &mut T and &RefCell are examples which are not unwind
我是一名优秀的程序员,十分优秀!