“`str`在编译时没有已知的恒定大小"是什么意思,最简单的解决方法是什么? [英] What does “`str` does not have a constant size known at compile-time” mean, and what's the simplest way to fix it?

查看:113
本文介绍了“`str`在编译时没有已知的恒定大小"是什么意思,最简单的解决方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to manipulate a string derived from a function parameter and then return the result of that manipulation:

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()
}

在建筑物上,出现此错误:

On building, I get this error:

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

这是怎么回事,最简单的解决方法是什么?

What's wrong here, and what's the simplest way to fix it?

推荐答案

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

TL;DR Don't use str, use &str. The reference is important.

问题可以简化为:

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

您正在尝试切片&str(但String&[T]Vec<T>等也会发生这种情况),但是没有引用结果.这意味着demo的类型将是str.要解决此问题,请添加&:

You are attempting to slice a &str (but the same would happen for a String, &[T], Vec<T>, etc.), but have not taken a reference to the result. This means that the type of demo would be str. To fix it, add an &:

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

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

In your broader example, you are also running into the fact that you are creating an allocated String inside of the match statement (via join) and then attempting to return a reference to it. This is disallowed because the String will be dropped at the end of the match, invalidating any references. In another language, this could lead to memory unsafety.

一个可能的解决方法是在函数运行期间存储创建的String,防止在创建新字符串之前将其释放:

One potential fix is to store the created String for the duration of the function, preventing its deallocation until after the new string is created:

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()
}

从编辑上来说,可能有更有效的编写此功能的方法. 格式化机制具有用于填充字符串的选项.您甚至可以只截断从join返回的字符串,而无需创建新的字符串.

Editorially, there's probably more efficient ways of writing this function. The formatting machinery has options for padding strings. You might even be able to just truncate the string returned from join without creating a new one.

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

What it means is harder to explain succinctly. Rust has a number of types that are unsized. The most prevalent ones are str and [T]. Contrast these types to how you normally see them used: &str or &[T]. You might even see them as Box<str> or Arc<[T]>. The commonality is that they are always used behind a reference of some kind.

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

Because these types don't have a size, they cannot be stored in a variable on the stack — the compiler wouldn't know how much stack space to reserve for them! That's the essence of the error message.

另请参阅:

  • What is the return type of the indexing operation?
  • Return local String as a slice (&str)
  • Why your first FizzBuzz implementation may not work

这篇关于“`str`在编译时没有已知的恒定大小"是什么意思,最简单的解决方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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