Rust 编程视频教程对应讲解内容-所有权

视频地址

头条地址:https://www.ixigua.com/i6765442674582356483
B站地址:https://www.bilibili.com/video/av78062009?p=1
网易云课堂地址:https://study.163.com/course/introduction.htm?courseId=1209596906#/courseDetail?tab=1

讲解内容

  1. 所有权是rust语言中最与众不同的特性,它让rust无需垃圾回收就可以保证内存安全。

  2. 计算机语言对内存的管理有三种方式:

  • 程序员自己分配和回收,例如:c/c++。
  • 语言自带GC,例如go语言。
  • rust语言为第三种方式,通过所有权系统管理内存,编译器在编译时根据规则对内存使用进行检查。

3. 栈和堆

  • 栈的操作是先进先出,存储于栈上的数据编译时都占用已知固定的大小。分配方式:直接分配
  • 编译时大小未知或者是变化的数据在堆上进行存储。 表示方式:用指针和大小表示

4. 变量作用域
一对花括号表示的范围,就是作用域,如下:

{
let i = 1;   --------------------------------|
...                                                   |
let j = 2; -------|                               |---i的作用域
...                   |------j的作用域         |
...----------------|--------------------------|  
}

说明:

  • 变量进入它的作用域有效
  • 离开作用域后无效
  1. 对于String类型,如:
let s = String::from("hello"); 
s.push_str(", world");

对于s,其所需要内存大小是变化的,因此需要在堆上进行分配。
对于在堆上分配的内存,编程语言一般有几种回收方式:

  • 有GC的语言自动回收,如go、java
  • 程序员手动回收,如c/c++
  • rust语言采用:当变量离开它的作用域后,就自动释放。

因此,在c语言中:

{
    let s = String::from("hello");
    ...
} //自动释放s,s不再有效

这是一个将 String 需要的内存返回给操作系统的很自然的位置:当 s 离开作用域的时候。当变量离开作用域,Rust 为我们调用一个特殊的函数。这个函数叫做 drop,在这里 String 的作者可以放置释放内存的代码。Rust 在结尾的 } 处自动调用 drop。

  1. 移动
    例子1:
let x = 5;  //将5绑定到x
let y = x;  //生成一个x的拷贝绑定到y

由于都是确定的类型,所以在存放在栈中。

例子2:

let s1 = String::from("hello");  //s1在堆上
let s2 = s1;    //移动s1到s2,此后不能再使用s1
println!("{}, world!", s1); //此处要报错,s1不能再使用

原因:

  • 两者的存放方式,画图 是浅拷贝
  • 如果s1继续有效,那么释放的时候(调用drop)会释放两次,会发生错误,因此这里s1不能再使用
    说明:rust语言默认是浅拷贝,同时将被拷贝的变量就会变得无效。
  1. 克隆
    如果要复制堆上的内容,则使用clone,例子:
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
  1. 在栈上的数据拷贝
    例如:
let x = 5;
let y = x;
println!("x = {}, y = {}", x, y);  //ok,x,y都在栈上

Rust 有一个叫做 Copy trait 的特殊注解,可以用在类似整型这样的存储在栈上的类型上。如果一个类型拥有 Copy trait,一个旧的变量在将其赋值给其他变量后仍然可用。Rust 不允许自身或其任何部分实现了 Drop trait 的类型使用 Copy trait。
常用的具有Copy trait的有:

  • 所有整数类型,比如 u32。
  • 布尔类型,bool,它的值是 true 和 false。
  • 所有浮点数类型,比如 f64。
  • 字符类型,char。
  • 元组,当且仅当其包含的类型也都是 Copy 的时候。比如,(i32, i32) 是 Copy 的,但 (i32, String) 就不是。
  1. 函数与作用域
    例子1:
fn main() {
    let s = String::from("hello");  // s 进入作用域
    takes_ownership(s);             // s 的值移动到函数里 ...
                                                 // ... 所以到这里不再有效
    let x = 5;                              // x 进入作用域
    makes_copy(x);                  // x 应该移动函数里,
                                               // 但 i32 是 Copy 的,所以在后面可继续使用 x
} // 这里, x 先移出了作用域,然后是 s。但因为 s 的值已被移走,所以不会有特殊操作
fn takes_ownership(some_string: String) { // some_string 进入作用域
    println!("{}", some_string);
} // 这里,some_string 移出作用域并调用 `drop` 方法。占用的内存被释放
fn makes_copy(some_integer: i32) { // some_integer 进入作用域
    println!("{}", some_integer);
} // 这里,some_integer 移出作用域。不会有特殊操作

例子2:

fn main() {
    let s1 = gives_ownership();         // gives_ownership 将返回值,移给 s1

    let s2 = String::from("hello");     // s2 进入作用域
    let s3 = takes_and_gives_back(s2);  // s2 被移动到takes_and_gives_back 中, 它也将返回值移给 s3
} // 这里, s3 移出作用域并被丢弃。s2 也移出作用域,但已被移走,所以什么也不会发生。s1 移出作用域并被丢弃
fn gives_ownership() -> String {             // gives_ownership 将返回值移动给调用它的函数
    let some_string = String::from("hello"); // some_string 进入作用域.
    some_string                              // 返回 some_string 并移出给调用的函数
}
// takes_and_gives_back 将传入字符串并返回该值
fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域
    a_string  // 返回 a_string 并移出给调用的函数
}

总结: 将值赋给另一个变量时移动它。当持有堆中数据值的变量离开作用域时,其值将通过 drop 被清理掉,除非数据被移动为另一个变量所有。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容