如何使用函数初始化数组? [英] How can I initialize an array using a function?

查看:32
本文介绍了如何使用函数初始化数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在 Rust 中创建一个包含 10 个空向量的数组,但是 [Vec::new();10] 不起作用,因为 Vec 没有实现 Copy.我怎样才能做到这一点,更一般地说,我怎样才能通过重复调用一个函数来初始化一个数组?

I want to create an array of 10 empty vectors in Rust, but [Vec::new(); 10] doesn't work as Vec doesn't implement Copy. How can I do this, and in more general terms how can I initialize a array by repeatedly calling a function?

推荐答案

我看到两种可能的方法

第一

使用宏的简单解决方案

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];

有点冗长,但即使是 标准库使用这种结构.

It's a bit verbose, but even the standard library uses this kind of construct.

第二

在意识到这个问题和另一个我之前回答过,我使用 nodrop

After realizing a connection between this question and another that I had answered before, I wrote this solution using 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];

还有一个测试,表明它不会泄漏内存

And a test that indicates that it does not leak memory

#[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)时发生panic,所以X(0)X(1), X(2) 必须删除.

In this test, the method X::new panics when creating X(3), so X(0), X(1), X(2) must be dropped.

其他

这里有一个不安全的解决方案.

这篇关于如何使用函数初始化数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆