关于rust:Rust教程二

所有权

先看一段代码

    let s3 = "hello";
    let s4 = s3;

    println!("{}", s3);

    let s1 = String::from("hello");
    let s2 = s1;

    //println!("{}", s1); //Error:^^ value borrowed here after move

    let array1 = [0,1,2,3,4,5];
    let ap = &array1;

    println!("{}", ap[3])
    println!("{:p},{:p}", &array1, ap);

打印s3的能够失常执行,打印s1的却报错。这是什么起因?
<1>s3的内容是栈里调配的, s3 = s4这是copy操作,相似复制了一个字符类型的变量s4.
如下类型的会是copy类型的。因为这些类型都是在栈里调配的,所以应用copy操作会很快

  • 所有整数类型
  • 布尔
  • 浮点
  • 字符(是字符,不是string!!)
  • 元组 (元组内的元素也都是copy类型的, (i32, i32), (i32, ‘aa’)是copy类型。(i32,String)的不是copy类型

<2>s1是String,不是字符类型。的内容是在堆里调配的,s2 = s1的操作是将s1指向内存”hello”的所有权转移给s2. 所以s1就被开释了

<3>借用操作符 &,这与C/C++相似,就是应用&获取内存地址。 ap = &array1理论就是获取array1的内存地址,付给ap.

所有权与函数

  • 函数参数所有权
    函数会有参数传入,此时所有权是否会产生变更?
    测试代码如下

    U32FnGetOwner

        let v:u32 = 32;
        println!("v address before fn:{:p}", &v);
        getU32Owner(v);
        println!("v address after fn:{:p}", &v);
        println!("{}", v)
    
        fn getU32Owner(v:u32) {
            println!("v address in fn:{:p}", &v);
            println!("v value:{}", v);
        }

    失常执行
    栈上调配的copy类型的变量,在函数内copy出新的变量。输入后果如下:

    v address before fn:0x7ff7bbc7a30c
    v address in fn:0x7ff7bbc798e4
    v value:32
    v address after fn:0x7ff7bbc7a30c
    32

    能够看到,在函数外和函数内,地址不同

    StringFnGetOwner

        let str1 = String::from("String owner");
        getOwner(str1);
    
        println!("{}", str1); //Error:^^^^ value borrowed here after move
    
        fn getStringOwner(s:String) {
            println!("Show s:{}",s);
        }

    会提醒错误信息,无奈编译通过
    堆上调配的变量,当在函数内产生所有权变更,传入函数变量的所有权也会变更

    str1曾经产生所有权变更,无奈再应用

    这就引起了一个问题,传入参数所有权都产生了变更,函数后就无奈应用了。如果想持续应用传入参数该如何做?答案是通过援用的形式,对于援用,学过C/C++的应该都很分明了

        let mut str4 = String::from("Beautiful ");
        let (str5, l ) = refStr(&mut str4);
    
        println!("{}", str4);
        println!("{}, len:{}", str5, l);
    
        fn refStr(s: &mut String) -> (String, usize) {
            s.push_str("sky");
    
            (s.to_string(), s.len())
        }

    输入后果如下

    Beautiful sky
    Beautiful sky, len:13

    通过援用,在函数内可能操作str4的内容(变量定义时以及函数参数定义处的 mut很重要,否则无奈在函数内变更内容),同时函数返回str4的所有权没有产生变更。

援用

对于援用学过C/C++的应该都比拟相熟,对于rust来说对于援用有以下几点须要留神

<1>可变援用只能有一个,不可变援用能够有多个。可变援用只能有一个的起因就是为了防止数据竞争,当有多个可变援用就会有数据竞争的可能。

    let mut ss = String::from("FFFF");
    let rr1 = &mut ss;
    let rr2 = &mut ss; //Error:cannot borrow `ss` as mutable more than once at a time

    println!("{}, {}", rr1, rr2)

<2>不能即存在可变援用又存在不可变援用

    let mut ss = String::from("FFFF");
    let rr1 = &ss;
    let rr2 = &mut ss; //Error:cannot borrow `ss` as mutable because it is also borrowed as immutable

    println!("{}, {}", rr1, rr2)

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理