我想创建一个Rc<str>
因为我想减少间接跟随访问Rc<String>
需求的2个指针.我需要使用一个,Rc
因为我真的拥有共享权.我详细介绍了我在字符串类型中遇到的更具体问题.
Rc 有一个?Sized
约束:
pub struct Rc<T: ?Sized> { /* fields omitted */ }
Run Code Online (Sandbox Code Playgroud)
我还听说Rust 1.2将提供适当的支持来存储未经过类型化的类型Rc
,但我不确定它与1.1的区别.
以str
案例为例,我的天真尝试(也就是从a构建String
)也失败了:
use std::rc::Rc;
fn main() {
let a: &str = "test";
let b: Rc<str> = Rc::new(*a);
println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)
error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
--> src/main.rs:5:22
|
5 | let b: Rc<str> = Rc::new(*a);
| ^^^^^^^ `str` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `str`
= note: required by `<std::rc::Rc<T>>::new`
Run Code Online (Sandbox Code Playgroud)
很明显,为了创建一个Rc<str>
,我需要复制整个字符串:RcBox
它本身就是一个unsized类型,将字符串本身与弱指针和强指针一起存储 - 上面的天真代码甚至没有意义.
我被告知一个人不能实例化这种类型,而是实例化Rc<T>
一个大小T
,然后强制它到一个unsized类型.给出的示例是存储特征对象:首先创建Rc<ConcreteType>
然后强制到Rc<Trait>
.但是,这没有任何意义之一:既不是这个也不是这个工作(你不能强迫&str
或String
到str
反正).
Cen*_*ril 14
从Rust 1.21.0开始,并按照RFC 1845的要求,创建Rc<str>
或Arc<str>
现在可以:
use std::rc::Rc;
use std::sync::Arc;
fn main() {
let a: &str = "hello world";
let b: Rc<str> = Rc::from(a);
println!("{}", b);
// or equivalently:
let b: Rc<str> = a.into();
println!("{}", b);
// we can also do this for Arc,
let a: &str = "hello world";
let b: Arc<str> = Arc::from(a);
println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)
(游乐场)
见<Rc as From<&str>>
和<Arc as From<&str>>
.
创建一个Rc<[T]>
可以通过强制和as
固定大小的数组来完成,例如强制可以按如下方式完成:
use std::rc::Rc;
fn main() {
let x: Rc<[i32; 4]> = Rc::new([1, 2, 3, 4]);
let y: Rc<[i32]> = x;
println!("{:?}", y);
}
Run Code Online (Sandbox Code Playgroud)
但是,这对字符串不起作用,因为它们没有原始的固定大小等效项来创建第一个值.有可能做得不安全,例如通过创建UTF-8编码Rc<[u8]>
并将其转换为Rc<str>
.理论上可以在crates.io上放一个箱子,但我现在找不到一个.
另一种选择是owning_ref
,它std::rc::Rc
本身并不完全,但应该允许,例如,RcRef<..., str>
指向一个Rc<String>
.(如果RcRef
统一使用Rc
,除了施工外,这种方法最有效.)
extern crate owning_ref;
use owning_ref::RcRef;
use std::rc::Rc;
fn main() {
let some_string = "foo".to_owned();
let val: RcRef<String> = RcRef::new(Rc::new(some_string));
let borrowed: RcRef<String, str> = val.map(|s| &**s);
let erased: RcRef<owning_ref::Erased, str> = borrowed.erase_owner();
}
Run Code Online (Sandbox Code Playgroud)
擦除意味着RcRef<..., str>
s可以来自多个不同的来源,例如a RcRef<Erased, str>
也可以来自字符串文字.
NB.在写作时,与擦除RcRef
需要夜间编译器,并根据owning_ref
与nightly
特点:
[dependencies]
owning_ref = { version = "0.1", features = ["nightly"] }
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1258 次 |
最近记录: |