Yoh*_*hei 3 string reference-counting slice rust
我想创建一些对str
with Rc
, without cloning 的引用str
:
fn main() {
let s = Rc::<str>::from("foo");
let t = Rc::clone(&s); // Creating a new pointer to the same address is easy
let u = Rc::clone(&s[1..2]); // But how can I create a new pointer to a part of `s`?
let w = Rc::<str>::from(&s[0..2]); // This seems to clone str
assert_ne!(&w as *const _, &s as *const _);
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
虽然原则上这是可能的,但标准库Rc
不支持您尝试创建的情况:对引用计数内存的一部分的计数引用。
但是,我们可以使用一个相当简单的包装器来获得字符串的效果,Rc
该包装器会记住子字符串范围:
use std::ops::{Deref, Range};\nuse std::rc::Rc;\n\n#[derive(Clone, Debug, Eq, Hash, PartialEq)]\npub struct RcSubstr {\n string: Rc<str>,\n span: Range<usize>,\n}\n\nimpl RcSubstr {\n fn new(string: Rc<str>) -> Self {\n let span = 0..string.len();\n Self { string, span }\n }\n fn substr(&self, span: Range<usize>) -> Self {\n // A full implementation would also have bounds checks to ensure\n // the requested range is not larger than the current substring\n Self {\n string: Rc::clone(&self.string),\n span: (self.span.start + span.start)..(self.span.start + span.end)\n }\n }\n}\n\nimpl Deref for RcSubstr {\n type Target = str;\n fn deref(&self) -> &str {\n &self.string[self.span.clone()]\n }\n}\n\nfn main() {\n let s = RcSubstr::new(Rc::<str>::from("foo"));\n let u = s.substr(1..2);\n \n // We need to deref to print the string rather than the wrapper struct.\n // A full implementation would `impl Debug` and `impl Display` to produce\n // the expected substring.\n println!("{}", &*u);\n}\n
Run Code Online (Sandbox Code Playgroud)\n这里缺少很多便利,例如Display
、Debug
、AsRef
、Borrow
、From
和Into
\xe2\x80\x94 的适当实现,我只提供了足够的代码来说明它是如何工作的。Rc<str>
一旦补充了适当的特征实现,这应该和(有一种边缘情况,即它不能传递给想要Rc<str>
特定存储的库类型)一样可用。
该板条箱arcstr
声称提供了这个基本想法的完成版本,但我尚未使用或研究过它,因此无法保证其质量。
该板条箱owning_ref
提供了一种保存对 Rc 或其他智能指针部分的引用的方法,但有人担心它的健全性,而且我不完全理解它适用于哪些情况(问题搜索目前有 3 个未解决的问题)。