有没有办法不必两次初始化数组

有没有办法不必两次初始化数组

本文介绍了有没有办法不必两次初始化数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将数组的每个元素初始化为非常量表达式.我可以这样做而不必首先将数组的每个元素初始化为一些无意义的表达式吗?以下是我希望能够执行的操作的示例:

I need to initialize each element of an array to a non-constant expression. Can I do that without having to first initialize each element of the array to some meaningless expression? Here's an example of what I'd like to be able to do:

fn foo(xs: &[i32; 1000]) {
    let mut ys: [i32; 1000];

    for (x, y) in xs.iter().zip(ys.iter_mut()) {
        *y = *x / 3;
    }
    // ...
}

这段代码给出了编译时错误:

This code gives the compile-time error:

error[E0381]: borrow of possibly uninitialized variable: `ys`
 --> src/lib.rs:4:33
  |
4 |     for (x, y) in xs.iter().zip(ys.iter_mut()) {
  |                                 ^^ use of possibly uninitialized `ys`

为了解决这个问题,我需要更改函数的第一行,用一些虚拟值来初始化 ys 的元素,如下所示:

To fix the problem, I need to change the first line of the function to initialize the elements of ys with some dummy values like so:

let mut ys: [i32; 1000] = [0; 1000];

有什么办法可以省略那个额外的初始化吗?将所有内容包装在 unsafe 块中似乎没有任何区别.

Is there any way to omit that extra initialization? Wrapping everything in an unsafe block doesn't seem to make any difference.

推荐答案

在某些情况下,您可以使用 std::mem::MaybeUninit:

In some cases, you can use std::mem::MaybeUninit:

use std::mem::MaybeUninit;

fn main() {
    let mut ys: MaybeUninit<[i32; 1000]> = MaybeUninit::uninit();
}

通过 MaybeUninit 包装器noreferrer">assume_init 是不安全的,因为访问未初始化的值在 Rust 中是未定义的行为,编译器不能再保证 ys 的每个值都会在它之前被初始化已读.

Removing the MaybeUninit wrapper via assume_init is unsafe because accessing uninitialized values is undefined behavior in Rust and the compiler can no longer guarantee that every value of ys will be initialized before it is read.

您的具体情况是 MaybeUninit 文档中的示例之一;阅读它以讨论此实现的安全性:

Your specific case is one of the examples in the MaybeUninit docs; read it for a discussion about the safety of this implementation:

use std::mem::{self, MaybeUninit};

fn foo(xs: &[i32; 1000]) {
    // I copied this code from Stack Overflow without
    // reading why it is or is not safe.
    let ys: [i32; 1000] = {
        let mut ys: [MaybeUninit<i32>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };

        let mut xs = xs.into_iter();

        for y in &mut ys[..] {
            if let Some(x) = xs.next().copied() {
                *y = MaybeUninit::new(x / 3);
            }
        }

        unsafe { mem::transmute(ys) }
    };
    // ...
}


不能收集到一个数组中,但如果你有一个Vec,你可以这样做:


You cannot collect into an array, but if you had a Vec instead, you could do:

let ys: Vec<_> = xs.iter().map(|&x| x / 3).collect();

对于您的特定问题,您还可以克隆传入的数组,然后对其进行变异:

For your specific problem, you could also clone the incoming array and then mutate it:

let mut ys = xs.clone();
for y in ys.iter_mut() { *y = *y / 3 }

这篇关于有没有办法不必两次初始化数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 18:05