什么"`str`没有在编译时知道的常量大小"是什么意思,什么是最简单的修复方法?

Bre*_*ugh 7 string pointers rust

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

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()
}
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

这里有什么问题,最简单的解决办法是什么?

She*_*ter 12

TL; DR请勿使用str,请使用&str.参考很重要.


这个问题可以简化为:

fn main() {
    let demo = "demo"[..];
}
Run Code Online (Sandbox Code Playgroud)

您正在尝试一个切片&str(但同样会发生的String,&[T],Vec<T>等),但并没有采取到结果的参考.这意味着该类型demostr.要解决此问题,请添加&:

let demo = &"demo"[..];
Run Code Online (Sandbox Code Playgroud)

在更广泛的示例中,您还遇到了这样一个事实:您正在语句中创建已分配String的内容match(via join),然后尝试返回对它的引用.这是不允许的,因为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()
}
Run Code Online (Sandbox Code Playgroud)

编辑,可能有更有效的方式来编写这个功能.该格式化机器有填充字符串选项.您甚至可以在join不创建新字符串的情况下截断返回的字符串.


这意味着更难以简洁地解释.Rust有许多未标注的类型.最普遍的是str[T].将这些类型与您通常看到它们的使用方式进行对比:&str&[T].您甚至可能将它们视为Box<str>Arc<[T]>.通用性是它们总是在某种参考之后使用.

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

也可以看看:

  • “这意味着什么更难以简洁地解释。” 然后继续简洁地解释一下。 (2认同)