更具体地说,为什么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>
)仍然存在:这是可能的,如果不是,为什么?
答案 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)
}
但是,您可以制作Arc<&[T]>
而不制作盒装切片:
use std::sync::Arc;
fn main() {
let v = vec![1, 2, 3];
let y: Arc<&[u32]> = Arc::new(&v[..]);
print!("{:?}", y)
}
然而,这似乎是类型系统中的一项研究,几乎没有实际价值。如果您真正想要的是Vec的视图,您可以在线程之间传递,Arc&lt;&amp; [T]&gt;会给你你想要的。如果你需要它在堆上,Arc<Box<&[T]>>
也可以正常工作。