如何构建 Rc<str>还是Rc [T] ? [英] How to build an Rc<str> or Rc<[T]>?

查看:44
本文介绍了如何构建 Rc<str>还是Rc [T] ?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个 Rc 因为我想减少访问 Rc 所需的 2 个指针的间接性.我需要使用 Rc 因为我确实拥有共享所有权.我在 另一个问题 我对我的字符串类型有更具体的问题.

I'd like to create an Rc<str> because I want reduce the indirection from following the 2 pointers that accessing an Rc<String> requires. I need to use an Rc because I truly have shared ownership. I detail in another question more specific issues I have around my string type.

Rc 有一个 ?Sized 绑定:

Rc has a ?Sized bound:

pub struct Rc<T: ?Sized> { /* fields omitted */ }

我还听说 Rust 1.2 将适当支持在 Rc 中存储未确定大小的类型,但我不确定这与 1.1 有何不同.

I've also heard that Rust 1.2 will come with proper support for storing unsized types in an Rc, but I'm unsure how this differs from 1.1.

str 为例,我的 天真的尝试(也这个用于从String) 失败:

Taking the str case as example, my naive attempt (also this for building from a String) fails with:

use std::rc::Rc;

fn main() {
    let a: &str = "test";
    let b: Rc<str> = Rc::new(*a);
    println!("{}", b);
}

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,我需要复制整个字符串:RcBox 本身就是一个未定义大小的类型,存储字符串本身除了弱指针和强指针——上面的代码甚至没有任何意义.

It's clear that in order to create an Rc<str>, I need to copy the whole string: RcBox would be itself an unsized type, storing the string itself alongside the weak and strong pointers — the naive code above doesn't even make sense.

我被告知不能实例化这样的类型,而是用一个大小的 T 实例化一个 Rc,然后将其强制为一个非大小的类型.给出的例子是存储一个 trait 对象:首先创建 Rc 然后强制转换为 Rc.但这也没有意义:this这个 工作(你不能从 &strStringstr 无论如何).

I've been told that one can not instantiate such type, but instead instantiate an Rc<T> with a sized T and then coerce it to an unsized type. The example given is for the storing a trait object: first create Rc<ConcreteType> and then coerce to Rc<Trait>. But this doesn't make sense either: neither this nor this work (and you can't coerce from &str or String to str anyway).

推荐答案

创建一个 Rc<[T]> 可以通过强制转换和 as-casts from固定大小的数组,例如可以通过以下方式进行强制转换:

Creating an Rc<[T]> can be done via coercions and as-casts from fixed sized arrays, e.g. coercions can be done as follows:

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.从理论上讲,crates.io 上可能有一个 crate,但我目前找不到.

However, this doesn't work for strings, since they have no raw fixed-sized equivalent to create the first value. It is possible to do unsafely, e.g. by creating a UTF-8 encoded Rc<[u8]> and transmuting that to Rc<str>. Theoretically there could be a crate on crates.io for it, but I can't find one at the moment.

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

An alternative is owning_ref, which isn't quite std::rc::Rc itself, but should allow, for example, getting an RcRef<..., str> pointing into an Rc<String>. (This approach will work best if one uses RcRef uniformly in place of Rc, except for construction.)

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 也可以来自字符串文字.

The erasing means that RcRef<..., str>s can come from multiple different sources, e.g. a RcRef<Erased, str> can come from a string literal too.

注意.在撰写本文时,使用 RcRef 进行擦除需要夜间编译器,并且依赖于具有 nightly 功能的 owning_ref:

NB. at the time of writing, the erasure with RcRef requires a nightly compiler, and depending on owning_ref with the nightly feature:

[dependencies]
owning_ref = { version = "0.1", features = ["nightly"] }

这篇关于如何构建 Rc&lt;str&gt;还是Rc [T] ?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆