AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 77219283
Accepted
Pioneer_11
Pioneer_11
Asked: 2023-10-03 10:00:46 +0800 CST2023-10-03 10:00:46 +0800 CST 2023-10-03 10:00:46 +0800 CST

获取已知数量的输入

  • 772

我希望在 Rust 中获取已知数量的输入。在本例中,我正在考虑欧拉项目第 54 题的扑克手牌,其中每行解析为两手牌,每手牌五张。对于这种情况,我发现有两种主要方法,但我都不喜欢。

方法一:

let mut buffer_1 = Vec::with_capacity(5);
for i in 0..5 {
    buffer_1.push(i)
}
assert_eq!(buffer_1.len(), 5);

方法二:

let mut buffer_2 = [None, 5];
for i in 0..5 {
    buffer_2[i as usize] = Some(i)
}

尽管在编译时大小已知,但方法 1 位于堆上,而方法 2 为我提供了一个可选值,其中我知道所有内容都是Some. 我理想的情况是能够将某些函数或集合收集到数组或类似的数组中。例如

fn array_from_colsure<T>(length: usize, closure: fn() -> T) -> Option<[T; length]> {
    // implementation
}
#[test]
fn array_from_closure_test() {
    let a: [i32; 5] = array_from_colsure(5, || {for i in 0..5 {i}}).unwrap()
}

澄清: 我希望找到具有此功能的东西,而不是从头开始创建它。

正如 Silvio Mayolo 的出色回答所示(自最初的问题以来,我对所需的功能进行了轻微的编辑),实现我的建议将需要大量的代码unsafe(更不用说为如此小的优化付出巨大的努力)。所以对于少数项目来说这样做是不明智的。

rust
  • 2 2 个回答
  • 62 Views

2 个回答

  • Voted
  1. Best Answer
    kmdreko
    2023-10-03T12:20:18+08:002023-10-03T12:20:18+08:00

    您可以使用std::array::from_fn:

    let buffer: [i32; 5] = std::array::from_fn(|i| i as i32);
    

    我还提供了ArrayVecarrayvec或tinyvec板条箱,这看起来像是您的第一种方法,但不会使用堆分配。

    • 5
  2. Silvio Mayolo
    2023-10-03T10:20:09+08:002023-10-03T10:20:09+08:00

    首先,我想说的是,你在这里所做的事情是过早优化的。您试图以编写可读、可维护的代码为代价来节省微秒。方法 1 具有正确的类型,从不重新分配,并且对于人类读者来说是显而易见的,因此您绝对应该使用方法 1。

    然而,让我们假设我们使用的是微处理器。我们在医院的一些嵌入式机器上运行,每个字节都很重要,并且堆分配存在问题。MaybeUninit可用于分配堆栈空间而不在其中存储任何内容。

    let mut buffer: [MaybeUninit<i32>; 5] = unsafe {
      MaybeUninit::uninit().assume_init()
    };
    

    这是一个相当令人困惑的说法。我们正在创建一些未初始化的内存,然后断言它已初始化。但事实并非如此:它尚未初始化。好吧,真正的assume_init意思是“该内存已根据类型所需进行了初始化”,并且由于数组仅包含,因此该类型未初始化就可以了。MaybeUninit

    for (i, elem) in buffer.iter_mut().enumerate() {
      elem.write(i as i32);
    }
    

    现在我们写入一些数据。我假设你的实际计算比 更复杂i as i32,但对于这个例子来说它会做得很好。

    let buffer = unsafe { transmute::<_, [i32; 5]>(buffer) };
    println!("{:?}", buffer);
    

    现在我们得到了一个可能未初始化的值的数组,我们知道这些值已经被初始化。由于MaybeUninit<T>和T具有相同的内存表示形式,因此我们可以将其中一种转换为另一种。transmute没有运行时开销,因为它实际上只是将一种类型的字节重新解释为另一种类型的字节。这是我们的整个代码块。

    let mut buffer: [MaybeUninit<i32>; 5] = unsafe {
      MaybeUninit::uninit().assume_init()
    };
    for (i, elem) in buffer.iter_mut().enumerate() {
      elem.write(i as i32);
    }
    let buffer = unsafe { transmute::<_, [i32; 5]>(buffer) };
    println!("{:?}", buffer);
    

    这里的数量unsafe应该会吓到你。它应该让你跑去叫 Rust 警察。我们通常不以这种方式编写代码是有原因的。但如果您发现自己处于百万分之一的情况,即额外的少量字节确实值得这么复杂,那么这是可以做到的。

    • 3

相关问题

  • 在匹配内重用函数时,匹配臂具有预期的不兼容类型

  • match 语句中的 Rust 类型转换

  • 如何强制匹配的返回类型为()?

  • 原始表示中的 Rust 枚举

  • 有没有办法直接简化 Result<String, VarError> 中 Ok("VAL") 的匹配

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    使用 <font color="#xxx"> 突出显示 html 中的代码

    • 2 个回答
  • Marko Smith

    为什么在传递 {} 时重载解析更喜欢 std::nullptr_t 而不是类?

    • 1 个回答
  • Marko Smith

    您可以使用花括号初始化列表作为(默认)模板参数吗?

    • 2 个回答
  • Marko Smith

    为什么列表推导式在内部创建一个函数?

    • 1 个回答
  • Marko Smith

    我正在尝试仅使用海龟随机和数学模块来制作吃豆人游戏

    • 1 个回答
  • Marko Smith

    java.lang.NoSuchMethodError: 'void org.openqa.selenium.remote.http.ClientConfig.<init>(java.net.URI, java.time.Duration, java.time.Duratio

    • 3 个回答
  • Marko Smith

    为什么 'char -> int' 是提升,而 'char -> Short' 是转换(但不是提升)?

    • 4 个回答
  • Marko Smith

    为什么库中不调用全局变量的构造函数?

    • 1 个回答
  • Marko Smith

    std::common_reference_with 在元组上的行为不一致。哪个是对的?

    • 1 个回答
  • Marko Smith

    C++17 中 std::byte 只能按位运算?

    • 1 个回答
  • Martin Hope
    fbrereto 为什么在传递 {} 时重载解析更喜欢 std::nullptr_t 而不是类? 2023-12-21 00:31:04 +0800 CST
  • Martin Hope
    比尔盖子 您可以使用花括号初始化列表作为(默认)模板参数吗? 2023-12-17 10:02:06 +0800 CST
  • Martin Hope
    Amir reza Riahi 为什么列表推导式在内部创建一个函数? 2023-11-16 20:53:19 +0800 CST
  • Martin Hope
    Michael A fmt 格式 %H:%M:%S 不带小数 2023-11-11 01:13:05 +0800 CST
  • Martin Hope
    God I Hate Python C++20 的 std::views::filter 未正确过滤视图 2023-08-27 18:40:35 +0800 CST
  • Martin Hope
    LiDa Cute 为什么 'char -> int' 是提升,而 'char -> Short' 是转换(但不是提升)? 2023-08-24 20:46:59 +0800 CST
  • Martin Hope
    jabaa 为什么库中不调用全局变量的构造函数? 2023-08-18 07:15:20 +0800 CST
  • Martin Hope
    Panagiotis Syskakis std::common_reference_with 在元组上的行为不一致。哪个是对的? 2023-08-17 21:24:06 +0800 CST
  • Martin Hope
    Alex Guteniev 为什么编译器在这里错过矢量化? 2023-08-17 18:58:07 +0800 CST
  • Martin Hope
    wimalopaan C++17 中 std::byte 只能按位运算? 2023-08-17 17:13:58 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve