我想在Rust中创建一个包含10个空向量的数组,但是[Vec::new(); 10]不起作用,因为Vec没有实现Copy。我该怎么做呢?更一般地说,我该怎么通过重复调用函数来初始化数组呢?
[Vec::new(); 10]
Vec
Copy
mqkwyuun1#
您可以使用数组的.map()方法来执行一般函数:
.map()
let arr: [Vec<u32>; 10] = [(); 10].map(|_| Vec::with_capacity(100));
(As Rust 1.55.0,2021年9月。Rust 1.63.0,2022年8月,考虑使用from_fn)
from_fn
6pp0gazn2#
对于您的特定情况,可以只使用Default:
Default
let v: [Vec<String>; 10] = Default::default();
对于一般情况,可以从函数中创建一个迭代器,然后使用ArrayVec将其收集到数组中:
ArrayVec
use arrayvec::ArrayVec; // 0.4.10 use std::iter; fn make<R>(f: impl FnMut() -> R) -> [R; 10] { let a: ArrayVec<_> = iter::repeat_with(f).collect(); a.into_inner() .unwrap_or_else(|_| panic!("Did not have enough elements")) } fn main() { let mut a = 0; let arr = make(|| { a += 3; a }); println!("{:?}", arr); // [3, 6, 9, 12, 15, 18, 21, 24, 27, 30] }
另请参阅:
dpiehjr43#
我看到两种可能的方法
第一个
使用宏的简单解决方案
macro_rules! array { ($v: expr; 1) => ([$v]); ($v: expr; 2) => ([$v, $v]); ($v: expr; 3) => ([$v, $v, $v]); ($v: expr; 4) => ([$v, $v, $v, $v]); ($v: expr; 5) => ([$v, $v, $v, $v, $v]); // until 32 } let a = array![Vec::new(); 3];
这有点冗长,但即使是标准库也使用这种结构。
第二个
在认识到这个问题与another that I had answered before之间的联系之后,我使用nodrop编写了这个解决方案
extern crate nodrop; macro_rules! array { ($e: expr; $n:expr) => ( { use std::mem; use std::ptr; use nodrop::NoDrop; struct ArrayBuilder<T> { len: usize, data: *mut T, } impl<T> Drop for ArrayBuilder<T> { fn drop(&mut self) { unsafe { while self.len > 0 { let offset = (self.len as isize) - 1; self.len -= 1; ptr::drop_in_place(self.data.offset(offset)); } } } } let mut v: NoDrop<[_; $n]> = NoDrop::new(unsafe { mem::uninitialized() }); // helps type inference for v if false { v[0] = $e; } let mut builder = ArrayBuilder { len: 0, data: (&mut *v as *mut _) as *mut _ }; unsafe { for i in 0..$n { ptr::write(builder.data.offset(i as isize), $e); builder.len = i + 1; } } builder.len = 0; v.into_inner() } ) } let a = array![Vec::new(); 3];
以及 * 指示 * 它不会泄漏内存的测试
# [test] fn test() { static mut COUNT: usize = 0; #[derive(Debug)] struct X(usize); impl Drop for X { fn drop(&mut self) { println!("drop {:?}", self.0); } } impl X { fn new() -> X { unsafe { if COUNT == 3 { panic!(); } let x = X(COUNT); COUNT += 1; x } } } array![X::new(); 6]; }
在此测试中,方法X::new在建立X(3)时会死机,因此必须卸除X(0)、X(1)、X(2)。
X::new
X(3)
X(0)
X(1)
X(2)
其他
有一个不安全的解决方案here。
unguejic4#
使用from_fn:
let array: [usize; 5] = core::array::from_fn(|i| i * 2); assert_eq!(array, [0, 2, 4, 8, 10]);
rkue9o1l5#
有一个名为arr_macro的板条箱,它可以完全满足您的需求:
fn main() { let array: [Vec<String>; 10] = arr![Vec::new(); 10]; println!("{:?}", array) // [[], [], [], [], [], [], [], [], [], []] }
5条答案
按热度按时间mqkwyuun1#
您可以使用数组的
.map()
方法来执行一般函数:(As Rust 1.55.0,2021年9月。Rust 1.63.0,2022年8月,考虑使用
from_fn
)6pp0gazn2#
对于您的特定情况,可以只使用
Default
:对于一般情况,可以从函数中创建一个迭代器,然后使用
ArrayVec
将其收集到数组中:另请参阅:
dpiehjr43#
我看到两种可能的方法
第一个
使用宏的简单解决方案
这有点冗长,但即使是标准库也使用这种结构。
第二个
在认识到这个问题与another that I had answered before之间的联系之后,我使用nodrop编写了这个解决方案
以及 * 指示 * 它不会泄漏内存的测试
在此测试中,方法
X::new
在建立X(3)
时会死机,因此必须卸除X(0)
、X(1)
、X(2)
。其他
有一个不安全的解决方案here。
unguejic4#
自生 rust 1.63起
使用from_fn:
rkue9o1l5#
有一个名为arr_macro的板条箱,它可以完全满足您的需求: