zoukankan      html  css  js  c++  java
  • 理解Rust的引用与借用

    https://www.jianshu.com/p/ac519d8c5ec9

    困惑

    接触Rust也一段时间了,但对References(引用) 、borrowing(借用) 、 &关键字、ref关键字、* 关键字,这几个词非常困惑。常见的问题不在乎下面几条:

    1. &关键字是代表引用还是借用?
    2. ref 和 & 有什么区别?
    3. 总是与c++的引用对比,他们意思相同?(因为人在学习中总与现有的知识对比,所以有了这一条)

    网上有很多对Rust中引用和借用部分进行翻译和解释。看得真是云里雾里,一会说借用,一会说引用,那到底是引用还是借用?

    现象

    rust中借用和引用的附带功效都一样,就是都有生命周期。借用使用&关键字,引用使用ref关键字。借用的对象是必须存在的,引用的对象可以虚拟的,后期附上对象。

    我看这网上的一段解释,Rust的引用和c++ 语言的引用完全不一样啊,c++ 语言说的是,引用类似变量别名,声明引用时,必须同时对其进行初始化。

    引用的声明方法:类型标识符 &引用名=目标变量名

    再看下出自《Programming Rust Fast, Safe Systems Development》

    in Rust terminology, we say that it borrows a reference to x. Given a
    reference r, the expression *r refers to the value r points to. These are very much like
    the & and * operators in C and C++
    Unlike C pointers, however, Rust references are never null: there is simply no way to
    produce a null reference in safe Rust. And Rust references are immutable by default:

    这怎么拿Rust引用与C++的指针进行比较了。都不知道那种是更合理的解释。

    实践

    实践出真知,还是动动手。

    • 首先证明的是引用是否可以为空。
    let ref a:i32;
    //a = 1;  // expected &i32,consider borrowing here: `&1`
    a = &1;
    

    上面代码能编译通过,这说明Rust中的引用和c++ 中的引用不是一个意思,更像c++ 中的指针类型。c++ 通过int *a来声明指针类型。

    • ref 与 & 的区别
    let ref a=2;
    let a = &2;
    

    两个值都是&i32类型。

    所以ref用在变量绑定与&用在表达式上是一样的效果。
    看到上一个例子的错误提示,consider borrowing here,那么&在Rust的表达式上可以看成是借用,这与c++ 取地址符是一个意思。

    struct B<'l> {
        pub a: &'l u32,
        // pub b: ref u32, expected type, found keyword `ref`
    }
    
    let ref a = &1;
    let b = B{ a: a };
    

    在类型声明上,&表示引用类型。

    • & 与 * 的关系

    那么&用在绑定上是怎么样的?其实&用在绑定上与*用在表达式上是一样的:

    let r=&1;
    let &a=r;
    let a=*r;
    

    两个值都是i32类型。

    如果上面的解释还没有让你明白他们之间的关系,那么通过代码直接输出具体类型,这能加深理解。

    #![feature(core_intrinsics)]
    
    fn main() {
        let x = &false;
        print_type_name_of(x);
    
        let &x = &false;
        print_type_name_of(x);
    
        let ref x = &false;
        print_type_name_of(x);
    }
    
    fn print_type_name_of<T>(_: T) {
        println!("{}", unsafe { std::intrinsics::type_name::<T>() })
    }
    
    &bool
    bool
    &&bool
    

    例子:

    #![feature(core_intrinsics)]
    enum Favour<'a> {
        Nor(u32),
        NorRef(u32),
        Ref(&'a u32),
        RefRef(&'a u32),
    }
    
    fn config(data: &u32) {
        println!("log data: {}", data);
    }
    
    // fn con(data: ref u32){  //expected type, found keyword `ref`
    //     println!("log data: {}", data);
    // }
    
    fn log(fav: Favour) {
        match fav {
            Favour::Nor(data) => {
                config(&data);
                print_type_name_of(data);
            },
            Favour::NorRef(ref data) => {
                config(data);
                print_type_name_of(data);
            },
            Favour::Ref(data) => {
                config(data);
                print_type_name_of(data);
            },
            Favour::RefRef(ref data) => {
                config(data);
                print_type_name_of(data);
            }
        }
    }
    
    fn print_type_name_of<T>(_: T) {
        println!("{}", unsafe { std::intrinsics::type_name::<T>() })
    }
    
    fn main() {
        log(Favour::Nor(1));
        log(Favour::Ref(&2));
        log(Favour::NorRef(3));
        log(Favour::RefRef(&4));
    }
    
    
    
    log data: 1
    u32
    log data: 2
    &u32
    log data: 3
    &u32
    log data: 4
    &&u32
    

    match的模式匹配上只能使用 ref,在函数声明上只能使用&来表示引用类型

    总结

    单纯Rust语言上考虑。
    我们在不同情况下解释&的意思:

    1. 在表达式上,表示的是借用。
    2. 在变量绑定上,表示解地址操作与*类似。
    3. 在类型声明上,表示引用类型。
    4. 在模式匹配上,无效关键字

    那么ref的通用解释是:

    1. 在表达式上,无效关键字
    2. 在变量绑定上,表示引用类型。
    3. 在类型声明上,无效关键字
    4. 在模式匹配上,表示引用类型。

    非要给区分ref&到底哪个是引用,哪个是借用。我们可以先从词性划分,引用我归类为名词,而借用归类为动词。&A在表达式上 表示借用A,这是一个动作,那结果就是产出一个引用类型。所以let ref B表示声明了一个引用类型,它只能绑定到某次借用动作上。

    所以ref 更适合叫引用, &叫借用。

    参考:

    when-to-ref-or
    ref-keyword-versus
    rust-by-example



    作者:kayryu
    链接:https://www.jianshu.com/p/ac519d8c5ec9
    来源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    审核系统
    ehcache 缓存
    tomcat 内存设置
    html5 开发 跨平台 桌面应用
    service thread 结合使用
    html5桌面应用
    鼠标 事件
    服务器 判断 客户端 文件下载
    使用github管理Eclipse分布式项目开发
    uub代码
  • 原文地址:https://www.cnblogs.com/dhcn/p/12678504.html
Copyright © 2011-2022 走看看