首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何构建Rc<str>或Rc<[T]>?

如何构建Rc<str>或Rc<[T]>?
EN

Stack Overflow用户
提问于 2015-07-28 19:45:06
回答 2查看 3.9K关注 0票数 27

我想要创建一个Rc<str>,因为我希望减少与访问Rc<String>所需的2个指针相同的间接方向。我需要使用Rc,因为我确实拥有共享的所有权。我在另一个问题中详细介绍了关于字符串类型的更具体的问题。

Rc 定界

代码语言:javascript
复制
pub struct Rc<T: ?Sized> { /* fields omitted */ }

我还听说,Rust 1.2将为在Rc中存储超大类型提供适当的支持,但我不确定这与1.1有何不同。

str为例,我的天真尝试 (也是从String构建的 )失败了:

代码语言:javascript
复制
use std::rc::Rc;

fn main() {
    let a: &str = "test";
    let b: Rc<str> = Rc::new(*a);
    println!("{}", b);
}
代码语言:javascript
复制
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`

很明显,为了创建一个Rc<str>,我需要复制整个字符串:RcBox本身就是一个不大小的类型,将字符串本身存储在弱指针和强指针的旁边--上面的简单代码甚至没有意义。

有人告诉我,不能实例化这类类型,而是用大小为Rc<T>T实例化它,然后强制它使用不大小的类型。给出的示例用于存储属性对象:首先创建Rc<ConcreteType>,然后强制使用Rc<Trait>。但是这也是没有意义的:都不起作用(而且您也不能强迫从&strStringstr )。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-18 03:04:04

从Rust 1.21.0开始,按照RFC 1845的要求,现在可以创建一个Rc<str>Arc<str>了:

代码语言:javascript
复制
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);
}

(游乐场)

>>

票数 38
EN

Stack Overflow用户

发布于 2015-07-28 23:36:06

从固定大小的阵列中创建Rc<[T]>可以通过矫顽器和as-casts来完成,例如矫顽器可以这样做:

代码语言:javascript
复制
use std::rc::Rc;

fn main() {
    let x: Rc<[i32; 4]> = Rc::new([1, 2, 3, 4]);

    let y: Rc<[i32]> = x;

    println!("{:?}", y);
}

但是,这并不适用于字符串,因为它们没有原始的固定大小的等价值来创建第一个值。不安全的操作是可能的,例如通过创建一个UTF-8编码的Rc<[u8]>并将其转换为Rc<str>。理论上说,crates.io上可能有一个板条箱,但目前我找不到。

另一种选择是owning_ref,它本身并不完全是std::rc::Rc,但是应该允许,例如,获取指向Rc<String>RcRef<..., str>。(这种方法最好的方法是统一使用RcRef代替Rc,但构造除外)。

代码语言:javascript
复制
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();
}

擦除意味着RcRef<..., str>s可以来自多个不同的来源,例如,RcRef<Erased, str>也可以来自字符串文本。

注意:在编写本报告时,“擦除RcRef”需要一个夜间编译器,并且取决于具有nightly特性的owning_ref

代码语言:javascript
复制
[dependencies]
owning_ref = { version = "0.1", features = ["nightly"] }
票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31685697

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档