我是rust的新手,我想声明一个类型化的变量而不对其进行初始化。在Rust中这可能吗?如果是这样,是明智的选择还是有更好的,更多的仿制方法呢?
我正在查看rustlings中的以下代码,由于无法推断x的类型而无法编译:
let x;
if x == 10 {
println!("Ten!");
}
所以,我尝试了这个:
let x: i32;
但是,现在编译器将在比较行上抛出一个错误,指出未声明x。
这很好,但是我想知道是否可以在没有分配的情况下声明类型。
let x: i32 = 10;
或者正确的方法是设计代码来避免这种情况吗?我来自C语言背景,对类型的懒惰可能有点太自在了。
答案 0 :(得分:0)
在rust中,变量的类型通常是根据上下文推断的。
上下文可以包括以下任何内容:
let x = String::new(); //x is now a String
fn foo() -> usize {
40
}
let x = foo(); //x is now usize
但是如果您没有要推断的类型,那么就不会为变量赋值:
let x;
然后,锈将无法推断出类型。因此,it will get mad at you。
此答案中需要解决的另一个问题;锈不允许读取未初始化的变量这一事实。以下值x
未初始化:
let x: u32;
读取未初始化的u32
的值可能不会做太多,但是请考虑以下因素:
struct MyString {
ptr: *const u8,
len: usize,
cap: usize,
}
如果我们要为此提供一个安全的包装器,那将是完全可以的,毕竟,这实际上就是stdlib String
的含义。但是,如果我们拥有一个未初始化的MyString
并尝试读取其内容,那么最终将从ptr
读取一个垃圾地址,并从一个垃圾len
和{{1 }}。这将导致读取垃圾指针,这是未定义的行为,这是rust消除的第一要务。
所以,回顾一下:
✓每个变量在运行时都必须具有可确定的类型(包括擦除的类型,因为它们也是具体的类型[{cap
和impl Trait
],但是dyn Trait
是特殊的。)
✓必须先为每个变量分配某种值,然后才能读取其值。
✓Rust非常努力地消除所有未定义的行为。
答案 1 :(得分:0)
您可以执行此操作,前提是编译器可以在尝试读取之前始终为其分配一个值,并且只会分配一次。这在特殊情况下可能会有所帮助。这是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"
}