【问题标题】:What does “`str` does not have a constant size known at compile-time” mean, and what's the simplest way to fix it?“`str` 在编译时没有已知的恒定大小”是什么意思,修复它的最简单方法是什么?
【发布时间】:2018-08-29 19:31:04
【问题描述】:

我正在尝试操作从函数参数派生的字符串,然后返回该操作的结果:

fn main() {
    let a: [u8; 3] = [0, 1, 2]; 
    for i in a.iter() {
        println!("{}", choose("abc", *i));
    }
}

fn choose(s: &str, pad: u8) -> String {
    let c = match pad {
        0 => ["000000000000000", s].join("")[s.len()..],
        1 => [s, "000000000000000"].join("")[..16],
        _ => ["00", s, "0000000000000"].join("")[..16],
    };
    c.to_string()
}

在构建时,我收到此错误:

error[E0277]: the trait bound `str: std::marker::Sized` is not satisfied
 --> src\main.rs:9:9
  |
9 |     let c = match pad {
  |         ^ `str` does not have a constant size known at compile-time
  |
  = help: the trait `std::marker::Sized` is not implemented for `str`
  = note: all local variables must have a statically known size

这里出了什么问题,最简单的解决方法是什么?

【问题讨论】:

    标签: string pointers rust


    【解决方案1】:

    TL;DR 不要使用str,使用&str。参考很重要。


    问题可以简化为:

    fn main() {
        let demo = "demo"[..];
    }
    

    您正在尝试对&str 进行切片(但String&[T]Vec<T> 等也会发生同样的情况),但没有参考结果。这意味着demo 的类型将是str。要修复它,请添加 &:

    let demo = &"demo"[..];
    

    在您更广泛的示例中,您还遇到了这样一个事实,即您正在match 语句(通过join)内创建分配的String,然后尝试返回对它的引用。这是不允许的,因为String 将在match 的末尾被删除,从而使任何引用无效。在另一种语言中,这可能会导致内存不安全。

    一个潜在的解决方法是在函数执行期间存储创建的String,防止在创建新字符串之前释放它:

    fn choose(s: &str, pad: u8) -> String {
        let tmp;
    
        match pad {
            0 => {
                tmp = ["000000000000000", s].join("");
                &tmp[s.len()..]
            }
            1 => {
                tmp = [s, "000000000000000"].join("");
                &tmp[..16]
            }
            _ => {
                tmp = ["00", s, "0000000000000"].join("");
                &tmp[..16]
            }
        }.to_string()
    }
    

    在编辑上,可能有更有效的方法来编写这个函数。 formatting machinery 具有填充字符串的选项。您甚至可以截断从join 返回的字符串,而无需创建新字符串。


    这意味着什么很难简洁地解释。 Rust 有许多 unsized 类型。最流行的是str[T]。将这些类型与您通常看到的使用方式进行对比:&str&[T]。您甚至可以将它们视为Box<str>Arc<[T]>。共同点是它们总是在某种引用后面使用。

    因为这些类型没有大小,它们不能存储在堆栈上的变量中——编译器不知道要为它们保留多少堆栈空间!这就是错误信息的本质。

    另见:

    【讨论】:

    • 比你。特别感谢指向字符串填充的指针,我将很快对其进行调查。像 Rust 或 Python 这样的语言,拥有可爱、庞大、几乎内置的库,是一把略带两刃的剑。还有很多东西要学...
    • “它的含义很难简洁地解释。”然后再简明扼要地解释一下。
    • @AndreKR 谢谢(我认为)!然而,这部分答案非常薄弱,因为它并没有真正解释 如何 某些东西可以“未调整大小”或为什么这样的概念有用,更不用说掩盖堆栈是什么了。
    • 我认为大多数语言都将其局部变量存储在堆栈中,因此这是一个熟悉的概念。错误消息中显示它的大小不足的原因 - 它没有实现Sized。我只是在阅读您的帖子之前没有建立联系。
    猜你喜欢
    • 1970-01-01
    • 2010-12-07
    • 2011-05-18
    • 2015-09-23
    • 1970-01-01
    • 2021-10-01
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    相关资源
    最近更新 更多