简体   繁体   English

如何在没有赋值的情况下注释生锈变量的数据类型?

[英]How do I annotate rust variables' data type without assignment?

I'm new to rust, and I'd like to declare a typed variable without initializing it. 我是生锈的新手,我想在没有初始化的情况下声明一个类型变量。 Is this possible in Rust? 这可能在Rust吗? If so, is it advisable or are there better, more rustacean-y ways to do it? 如果是这样,是否可行,或者是否有更好的,更多的方法可以做到这一点?

I'm looking at the following code from rustlings which fails to compile because it can't infer the type of x: 我期待在从下面的代码窸窣从而未能编译,因为它不能推断出x的类型:

    let x;
    if x == 10 {
        println!("Ten!");
    }

So, I tried this: 所以,我试过这个:

let x: i32;

however, now the compiler will throw an error on the comparison line saying that x hadn't been declared. 但是,现在编译器会在比较行上抛出一个错误,说明x尚未声明。

This works fine, but I was left wondering if one can declare the type without an assignment. 这工作正常,但我想知道是否可以声明没有赋值的类型。

let x: i32 = 10;

Or is the correct way to do it involve designing your code to avoid such situations in the first place? 或者正确的方法是设计代码以避免首先出现这种情况? I come from a C background and I'm probably a little too comfortable with being lazy with types. 我来自C背景,我可能有点太懒了与类型懒惰。

In rust, the type of a variable is usually inferred from the context. 在生锈中,变量的类型通常从上下文中推断出来。
The context can include any of the following: 上下文可以包括以下任何内容:

  • The type of the value being assigned: 分配的值的类型:
let x = String::new(); //x is now a String
  • The return type of the function being called: 被调用函数的返回类型:
fn foo() -> usize {
    40
}
let x = foo(); //x is now usize

But if you don't have a type to infer, as in there is no assignment to the variable: 但是如果你没有要推断的类型,就像没有对变量的赋值:

let x;

Then rust cannot infer the type. 然后生锈不能推断出类型。 Therefore, it will get mad at you . 因此, 它会生你的气

Another problem that needs to be addressed in this answer; 在这个答案中需要解决的另一个问题; the fact that rust doesn't allow the reading of uninitialized variables. 生锈不允许读取未初始化变量的事实。 The following value, x is uninitialized: 以下值, x未初始化:

let x: u32;

Reading the value of an uninitialized u32 probably wouldn't do too much, but consider the following: 读取未初始化的u32的值可能不会做太多,但请考虑以下内容:

struct MyString {
    ptr: *const u8,
    len: usize,
    cap: usize,
}

If we were to provide a safe wrapper around this, this would be perfectly fine, after all, this is essentially what the stdlib String boils down to. 如果我们提供一个安全的包装器,这将是完全没问题,毕竟,这基本上是stdlib String归结为。 But, if we were to own an uninitialized MyString and tried to read its contents, we'd end up reading a garbage address from the ptr , and a garbage len and cap . 但是,如果我们要拥有一个未初始化的MyString并尝试读取它的内容,我们最终会从ptr读取一个垃圾地址,以及垃圾lencap This would lead to reading a garbage pointer, which is undefined behavior, which is rust's #1 priority to eliminate. 这将导致读取垃圾指针,这是未定义的行为,这是生锈的第一优先消除。

So, to recap: 所以,回顾一下:
✓ Every variable must have a type determinable at runtime (Including erased types, because those are concrete types too [ dyn Trait and impl Trait ], but impl Trait is special.) ✓每个变量必须具有在运行时可确定的类型(包括已删除的类型,因为这些类型也是具体类型[ dyn Traitimpl Trait ],但impl Trait是特殊的。)
✓ Every variable must be assigned some kind of value before you can read its value. ✓在读取其值之前,必须为每个变量分配某种值。
✓ Rust tries very hard to eliminate all undefined behavior. ✓Rust非常努力地消除所有未定义的行为。

You can do this, provided that the compiler can see that it will always have a value assigned before you try to read from it, and it will only ever be assigned once. 您可以这样做,前提是编译器可以看到它在您尝试从中读取之前始终会分配一个值,并且它只会被分配一次。 This can be helpful in peculiar circumstances. 这在特殊情况下会有所帮助。 Here's a slightly contrived example . 这是一个有点人为的例子

fn main() {
    let some_cond = false;

    let x;
    let y;
    let z: u8;

    if some_cond {
        x = 1;
        y = 2;
        z = 3;
    } else {
        x = 4;
        y = 5;
        z = 6;
    }

    println!("x = {}", x); // "x = 4"
    println!("y = {}", y); // "y = 5"
    println!("z - 10 = {}", z.wrapping_sub(10)); // "z - 10 = 252"
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM