我正在学习Rust,发现在变量名前加下划线会让编译器不警告未使用的变量。我想知道为什么会有这个功能,因为未使用的变量是被不赞成的。
我正在学习Rust,发现在变量名前加下划线会让编译器不警告未使用的变量。我想知道为什么会有这个功能,因为未使用的变量是被不赞成的。
#[must_use]
类型的函数,但在你的特定情况下,你知道可以安全地忽略该值。可以使用_
模式来实现这一点(它不是变量绑定,而是自己的模式,但这可能是下划线前缀约定的来源),但你可能想记录为什么要忽略该值,或者该值是什么。在我的经验中,这在测试中特别常见。used_underscore_binding
lint就强制执行这个约定。_
,因为_
不是变量绑定,而且该值不会像变量绑定一样在封闭块的末尾被丢弃。_
模式来实现这个。let _=
和 let _foo=
有着稍微不同的行为。两者都可以消除警告,但是 let _
会导致返回值在语句结束时被 Drop
,而不是在作用域结束时被 Drop
,因为没有绑定来持有该值。 - loganfsmyth_s
。fn add_numbers(f: i32, _s: i32) -> i32 {
f + 1
}
_s
变量使我们能够保持签名不变,即使我们没有实现它。如果我们发现不需要_s
,但因为我们的库在许多不同的项目中使用,我们不想改变函数的API,这也适用。这可能是好的做法,也可能是坏的做法,但在_s
需要保留且不执行任何操作的情况下可能会很有用。我们也可以在这里使用_
,但_s
未来可能具有更多的意义。Drop
并且您关心该逻辑发生的位置时,这可以很有用。在此示例中,您可以看到需要_result
变量,以便Drop
在最后发生。fn main() {
let mut num = 1;
// let _ = try_add_numbers(&mut num); // Drop is called here for _
let _result = try_add_numbers(&mut num); // without the _result we have a warning.
println!("{}", num);
// Drop is called here for the _result
}
// keep the api the same even if an aurgument isn't needed anymore or
// has not been used yet.
fn add_numbers(f: i32, _s: i32) -> i32 {
f + 1
}
// This function returns a result
fn try_add_numbers(i: &mut i32) -> Result<GoodResult, GoodResult> {
if *i > 3 {
return Err(GoodResult(false));
}
*i = add_numbers(*i, 0);
Ok(GoodResult(true))
}
struct GoodResult(bool);
impl Drop for GoodResult {
fn drop(&mut self) {
let &mut GoodResult(result) = self;
if result {
println!("It worked");
} else {
println!("It failed");
}
}
}
let _result = try_add_numbers(&mut num);
,那么我们就有了一个变量,它在main函数结束之前都处于范围内,直到drop被调用为止。如果我们使用let _ = try_add_numbers(&mut num);
,我们仍然不会收到警告,但是drop会在语句的末尾被调用。如果我们没有let绑定而使用try_add_numbers(&mut num);
,我们会收到警告。这个程序的输出结果取决于我们如何在try_add_numbers函数中使用它们。It worked
2
或者
2
It worked
因此,在涉及到程序输出时,需要根据需要选择_
和_named
变量。请在Playground中尝试我的示例以加深理解。
Drop
的情况下,手动调用drop
比使用_result
来隐藏实际上正在使用_result
更有意义。在需要调用drop
的情况下,使用的值仍然很明显,而且需要在某个地方删除它也很明显。 - Loïc Faure-Lacroixlet a
是一个值绑定,会分配一个栈空间来存储它的值。let _a
表现得像let a
,除此之外,它被标记为intentional
,这样编译器就不会在_a
未使用时弹出警告。let _
是一种模式,_
是一个保留标识符
,不能在其他地方使用。这不会导致栈空间的分配,所以=
右侧的值将很快被释放。以下是一个示例: Playground
pub struct Node {
value: usize,
}
impl Drop for Node {
fn drop(&mut self) {
println!("drop() {}", self.value);
}
}
pub fn square() {
let a = Node { value: 1 };
let _a = Node { value: 2 };
let _ = Node { value: 3 };
println!("Hello, world!");
}
fn main() {
square();
}
输出结果为:
drop() 3
Hello, world!
drop() 2
drop() 1
let _
actually is a no-op. It does nothing. You can check the assembly yourself. let _ = Node { value: 3 };
and Node { value: 3 };
produce the exact same results. I created a small example to show this. You can try my example and this example above (both with and without let _
, and you'll see the assembly is the same). https://godbolt.org/z/5vnr1ExWe - What let _
is useful for, is for ignoring compiler warnings such as warning: unused Result that must be used
- Kobato只需定义变量的类型,例如:
fn names(){ //this case the function gives an warning like "help: if this is intentional, prefix it with an underscore: `_myname`"
let myname = "yash";
}
因此,通过您代码中的最新更改,您可以克服此错误:
fn name(){ //here warning won't come
let myname: &str = "bash"
}
我通过谷歌搜索与匹配变量相关的警告时偶然发现了这里。这与其有关。
有时您可能会有一些代码,其中您获得一个Result
并希望匹配情况,但您不关心错误值。您可以使用_
来代替_e
或其他东西,它明确地不绑定。以下是一个具体示例。我们不关心错误的值,因为我们正在返回自己的值。
fn some_method() -> Result<u32, MyCustomError> {
// ...
let id: u32 = match some_str.parse() {
Ok(value) => value,
Err(_) => return Err(MyCustomError::Blah)
};
// ...
}
_e
”。这意味着“实际上,你可以只使用_
。”这怎么回答问题呢? - mcartonErr(e)
的事情,并收到了一个关于它未被使用的错误。也许编译器甚至建议像use _e to avoid the warning
这样的东西,然后我就来到了这里。我可能随后学会了可以使用_
来避免错误。假设这就是OP正在处理的问题,那么它回答了潜在的关注点。无论如何,既然我因为_e
来到了这里,我相信其他人也会受益于建议使用_
。 - Captain Man