是否可以创建Arc&lt; [T]&gt;从Vec <t>?

时间:2017-06-19 17:44:55

标签: rust

更具体地说,为什么doesn't Arc<T>from_raw does期间使用动态大小T实施Box<T>

use std::sync::Arc;

fn main() {
    let x = vec![1, 2, 3].into_boxed_slice();
    let y = Box::into_raw(x);
    let z = unsafe { Arc::from_raw(y) }; // ERROR
}

play

正如评论中所指出的,Arc::from_raw 必须与来自Arc::into_raw的指针一起使用,因此上述示例没有意义。我的原始问题(是否可以从Arc<[T]>创建Vec<T>)仍然存在:这是可能的,如果不是,为什么?

3 个答案:

答案 0 :(得分:8)

从Rust 1.21.0开始,你可以这样做:

let thing: Arc<[i32]> = vec![1, 2, 3].into();

这是RFC 1845启用的:

  

此外:还会添加From<Vec<T>> for Rc<[T]>From<Box<T: ?Sized>> for Rc<T>

     

还会为Arc添加相同的API。

在内部,这是uses a method called copy_from_slice,因此Vec的分配不会被重复使用。有关详细原因,请查看DK.'s answer

答案 1 :(得分:7)

没有

首先,正如评论中已经提到的那样,你不能像这样肆无忌惮地抛出原始指针。引用the documentation of Arc::from_raw

  

原始指针必须先前通过调用Arc::into_raw返回。

您绝对必须在您使用unsafe方法时阅读文档。

其次,你想要的转换是不可能的。 Vec<T>Box<[T]>有效,因为在内部,Vec<T>实际上是(Box<[T]>, usize)对。因此,所有方法都可以让您访问内部Box<[T]>指针[1]。但是,Arc<[T]> Box<[T]>物理兼容,因为它必须包含引用计数。 Arc<T>指向的内容与Box<T>指向的内容具有不同的大小和布局。

Vec<T>Arc<[T]>的唯一方法是在引用计数分配中重新分配向量的内容......我不知道任何方式去做。我不相信它有什么特别的原因无法实施它只是没有[2]。

所有这一切,我认为无法使用Arc::into_raw / Arc::from_raw动态大小的类型是一个错误。使用动态大小的类型来获取Arc肯定是可能的......尽管只能通过从指针转换为固定大小的类型。

[1]:不完全。 Vec<T> 它还必须将切片缩小为不包含未初始化的元素。

[2]:总的来说,Rust并没有很好地支持一般分配动态大小的东西。特别是这个漏洞的部分原因可能是Box<[T]> 无法直接分配数组,这可能是因为Box<T>存在,因为Vec<T>曾经是语言本身的一部分,为什么当Vec<T>已经存在时,你会将数组分配添加到Box&#34;为什么没有Vec呢?&#34; 因为共享所有权,你永远无法构建

答案 2 :(得分:0)

Arc<[T]>Arc,其中包含指向T切片的指针。但是[T]实际上并没有在编译时调整大小,因为编译器不知道它会有多长(相对于&amp; [T]只是一个参考,因此具有已知的大小)。

use std::sync::Arc;

fn main() {
    let v: Vec<u32> = vec![1, 2, 3];
    let b: Box<[u32]> = v.into_boxed_slice();
    let y: Arc<[u32]> = Arc::new(*b);
    print!("{:?}", y)
}

Play Link

但是,您可以制作Arc<&[T]>而不制作盒装切片:

use std::sync::Arc;

fn main() {
    let v = vec![1, 2, 3];
    let y: Arc<&[u32]> = Arc::new(&v[..]);
    print!("{:?}", y)
}

Shared Ref Play Link

然而,这似乎是类型系统中的一项研究,几乎没有实际价值。如果您真正想要的是Vec的视图,您可以在线程之间传递,Arc&lt;&amp; [T]&gt;会给你你想要的。如果你需要它在堆上,Arc<Box<&[T]>>也可以正常工作。