我想在Rust中创建一个包含10个空向量的数组,但[Vec::new(); 10]
不起作用,因为Vec
没有实现Copy
。我怎么能这样做,更一般地说,如何通过重复调用函数来初始化数组?
答案 0 :(得分:3)
我看到两种可能的方法
<强>第一强>
使用宏
的简单解决方案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];
它有点冗长,但即使是standard library也使用了这种结构。
<强>第二强>
在实现此问题与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)
。
<强>其他强>
有一个不安全的解决方案here。
答案 1 :(得分:2)
对于您的具体情况,您可以使用Default
:
let v: [Vec<String>; 10] = Default::default();
对于一般情况,您可以从函数中创建迭代器,然后使用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]
}
另见:
答案 2 :(得分:0)
有一个名为arr_macro的箱子可以完全满足您的需求:
fn main() {
let array: [Vec<String>; 10] = arr![Vec::new(); 10];
println!("{:?}", array) // [[], [], [], [], [], [], [], [], [], []]
}