在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);

}

如果还有其它的场景或用途,请联系我,谢谢!

更多推荐