Rust:关于下划线“_”的七种场景总结
·
在Rust语言中,下划线“_”相较于其它语言,更经常出现,有也不一样的意义,专门的参考资料也比较少。这里简单归纳一下。谨供大家参考。
一、代码
fn main(){
para_("hello world");
lifetime_();
variable_();
type_erase_();
ref_();
other_item_();
type_inference_();
}
二、与参数相结合
// parameter :对输入的参数不处理
fn para_(_:&str){
println!("hello world!")
}
三、与生命周期相结合
// lifetime
// 任意的生命周期
fn lifetime_(){
println!("请参看以下源代码中的例子!");
// https://doc.rust-lang.org/src/alloc/borrow.rs.html
// impl<B: ?Sized + ToOwned> Clone for Cow<'_, B> {
// fn clone(&self) -> Self {
// match *self {
// Borrowed(b) => Borrowed(b),
// Owned(ref o) => {
// let b: &B = o.borrow();
// Owned(b.to_owned())
// }
// }
// }
// }
}
四、与变量相结合
// 忽略生成的变量结果
fn variable_(){
// 场景1:
let _ = add(2,3); //对add函数的结果忽略; 此时“_"并不是变量名!
// 场景2:
let my_tuple = Mytuple(1,2,3,String::from("hello world"));
let Mytuple(a,_,b,c) = my_tuple;
println!("a:{} b:{},c:{}",a,b,c);
// 场景3:
let value:Option<i32> = Option::None;
match value{
Some(_) => {
println!(" this is some value");
}
None => {
println!("None");
}
}
println!("work is fininshed!");
fn add(x:i32,y:i32)->i32{
x+y
}
struct Mytuple(i32,i32,i32,String);
}
五、用于类型擦除
// 类型擦除
fn type_erase_(){
println!("下面是type erase的例子!");
fn process_method<T>(f: unsafe fn(*const ()),data:&T) {
let ptr: *const () = data as *const T as _; // 这里"_"是 type erase
unsafe{
f(ptr)
};
}
fn data_const_ptr<T>(data: &T) -> *const () {
data as *const T as _ // 这里"_"是 type erase
}
}
六、不move所有权
在“*self”的场景下,如果没有和ref或ref mut相结合使用,很可能会move所有权。但是“_”让我们看到类似的效果。
fn ref_(){
println!("下面是'_'起到ref的作用的例子");
example_1();
example_2();
fn example_1(){
println!("下面是源码,谨供参考!");
// *self: 为什么可以直接解引用?*self: 字段中没有ref,但有“_”,也可以
//https://doc.rust-lang.org/src/alloc/borrow.rs.html
// impl<B: ?Sized + ToOwned> Cow<'_, B> {
// pub const fn is_borrowed(&self) -> bool {
// match *self {
// Borrowed(_) => true,
// Owned(_) => false,
// }
// }
// pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
// match *self {
// Borrowed(borrowed) => {
// *self = Owned(borrowed.to_owned());
// match *self {
// Borrowed(..) => unreachable!(),
// Owned(ref mut owned) => owned,
// }
// }
// Owned(ref mut owned) => owned,
// }
// }
// }
}
fn example_2(){
use std::borrow::Borrow;
use std::ops::Deref;
let dog = Dog::Borrowed("hello world");
model_1(&dog);
model_2(&dog);
// *dog: 字段中没有ref,但有“_”,也可以
fn model_1(dog: &Dog<'_,str>){
match *dog{
Dog::Borrowed(_) => {
println!("Borrowed");
}
Dog::Owned(_) => {
println!("Owned");
}
}
}
// 少了ref,将报错!
fn model_2(dog: &Dog<'_,str>){
match *dog{
Dog::Borrowed(_) => {
println!("Borrowed");
}
Dog::Owned(ref own) => {
println!("Ownned :{:?}",own);
}
}
}
enum Dog<'a,B:?Sized+'a> where B: ToOwned{
Borrowed(&'a B),
Owned( <B as ToOwned>::Owned),
}
impl<B: ?Sized + ToOwned> Deref for Dog<'_, B> where B::Owned: Borrow<B>,
{
type Target = B;
fn deref(&self) -> &B {
match *self {
Dog::Borrowed(borrowed) => borrowed,
Dog::Owned(ref owned) => owned.borrow(),
}
}
}
}
}
七、代表其它选项
经常在match相结合用法中看到。例如:
fn other_item_(){
let myenum = MyEnum::A;
match myenum {
MyEnum::A => {
println!("A");
}
_ =>{
println!("other!");
},
}
enum MyEnum{
A,
B,
C,
D,
E,
}
}
八、类型推断
有时可以用“_”进行类型推断,减轻开发者负担。
fn type_inference_(){
let v :Vec<_> = vec![1,2,3,4];
let s:_ = String::from("hello world");
println!("v : {:?}",v);
println!("s : {:?}",s);
}
如果还有其它的场景或用途,请联系我,谢谢!
更多推荐

所有评论(0)