#![feature(new_uninit)]
use std::rc::Rc;
use std::mem::MaybeUninit;
pub fn test<const N: usize>() -> Rc<[usize; N]> {
let mut r: Rc<[MaybeUninit<usize>]> = Rc::new_uninit_slice(N);
for f in Rc::get_mut(&mut r).unwrap().iter_mut() {
f.write(42);
}
// SAFETY:
// * all elements are initialized
// * the metadata can safely be dropped since it's encoded in the returned type
// * layout of `MaybeUninit<T>` is the same as `T`
unsafe { Rc::from_raw(Rc::into_raw(r).cast()) }
}
use std::mem::MaybeUninit;
use std::rc::Rc;
pub fn test() -> Rc<[usize; 1024]> {
let mut rc = Rc::new(MaybeUninit::<[usize; 1024]>::uninit());
// SAFETY: `MaybeUninit<[T; N]>` and `[MaybeUninit<T>; N]` have the same layout,
// and both can stay uninitialized.
let data = unsafe {
&mut *(Rc::get_mut(&mut rc).unwrap() as *mut MaybeUninit<[usize; 1024]>
as *mut [MaybeUninit<usize>; 1024])
};
for item in data {
item.write(42);
}
// SAFETY: `MaybeUninit<T>` and `T` have the same layout, and we initialized it above.
unsafe { Rc::from_raw(Rc::into_raw(rc).cast::<[usize; 1024]>()) }
}
use std::rc::Rc;
pub fn test() -> Rc<[usize; 1024]> {
let boxed_slice = vec![42; 1024].into_boxed_slice();
let ptr = Box::into_raw(boxed_slice) as *mut [usize; 1024];
// SAFETY: the data of a `[T; N]` has the same layout as that of
// a `[T]` and we allocated a slice of the right size.
let b = unsafe { Box::from_raw(ptr) };
b.into()
}
3条答案
按热度按时间aiazj4mn1#
据我所知,目前没有办法直接分配
Rc<[T; N]>
而不从stable的堆栈中复制数据,每晚可以手动初始化Rc
,如下所示:apeeds0o2#
不需要每晚伸手,这可以在马厩里完成(注意:仅在启用优化时不复制):
xytpbqjk3#
在this answer的基础上构建,首先可以创建一个
Box<[usize; 1024]>
,然后将其转换为Rc
,因为Rc<T>
实现了From<Box<T>>
:Godbolt