pc端网站设计规范,关于青岛的网页设计,请人做网站设计的方案,wordpress4.7更新说明说句题外话#xff0c;这篇文章真心很难#xff0c;有看不懂可以在评论区问#xff0c;我会尽快作答的。
喜欢的话别忘了点赞、收藏加关注哦#xff08;加关注即可阅读全文#xff09;#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵#xff01;(#xff65;ω…说句题外话这篇文章真心很难有看不懂可以在评论区问我会尽快作答的。
喜欢的话别忘了点赞、收藏加关注哦加关注即可阅读全文对接下来的教程有兴趣的可以关注专栏。谢谢喵(ω)
15.7.1. 内存泄漏
Rust极高的安全性使得内存泄漏很难出现但并不是完全不可能。
例如使用RcT和RefCellT就可能创造出循环引用造成内存泄漏每个指针的引用计数都不会减少到0值也不会被清理。
看个例子
use crate::List::{Cons, Nil};
use std::cell::RefCell;
use std::rc::Rc;#[derive(Debug)]
enum List {Cons(i32, RefCellRcList),Nil,
}impl List {fn tail(self) - OptionRefCellRcList {match self {Cons(_, item) Some(item),Nil None,}}
}fn main() {let a Rc::new(Cons(5, RefCell::new(Rc::new(Nil))));println!(a initial rc count {}, Rc::strong_count(a));println!(a next item {:?}, a.tail());let b Rc::new(Cons(10, RefCell::new(Rc::clone(a))));println!(a rc count after b creation {}, Rc::strong_count(a));println!(b initial rc count {}, Rc::strong_count(b));println!(b next item {:?}, b.tail());if let Some(link) a.tail() {*link.borrow_mut() Rc::clone(b);}println!(b rc count after changing a {}, Rc::strong_count(b));println!(a rc count after changing a {}, Rc::strong_count(a));
}首先创建了一个链表List使用RefCellT包裹RcT使其内部值可被修改 通过impl块为List写了一个叫tail的方法用于获取List下Cons变体附带的第二个元素如果有就返回其值用Some封装是Nil就返回None。 然后在main函数创建了a、b两个List的实例b内部共享了a的值。这种链表的代码看着就犯恶心所以我把其结构图放在 这里 main函数里还通过Rc::strong_count获取了a和b的强引用数量使用自定义的tail方法获了Cons附带的第二个元素用println!打印出来。 下面使用if let语句把a的Cons的第二个值绑在link上通过borrow_mut方法获得其可变引用Cons使用解引用符号*把它转为Cons最后把b的值通过Rc::clone共享赋给了link也就改变了a内部的结构变为了 PS:我觉得自己画的太烂了所以这里就换成The Rust Programming Language里的图片了
输出:
a initial rc count 1
a next item Some(RefCell { value: Nil })
a rc count after b creation 2
b initial rc count 1
b next item Some(RefCell { value: Cons(5, RefCell { value: Nil }) })
b rc count after changing a 2
a rc count after changing a 2第1行到第5行刚开始创建a时引用数量就为1当b被声明时a被共享了所以此时a的引用计数为2b为1。
第六行到第7行if let语句把a的内部结构改变了使a的第二个元素指向bb的引用数量加1变为2。此时a指向了bb又指向了a就会造成循环引用。
当a和b都走出了作用域Rust删除了变量b 这将b的引用计数从 2 减少到 1。此时RcList在堆上的内存不会被删除因为它的引用计数是1而不是0。然后 Rust 删除a 这会将a的RcList实例的引用计数从 2 减少到 1如图所示。这个实例的内存也不能被删除因为另一个实例的内存 RcList实例仍然引用它。分配给列表的内存将永远保持未回收状态。
接下来我们看看循环引用的内容是什么,使用这条代码
println!(a next item {:?}, a.tail());Rust 将尝试打印此循环其中a指向b指向a等等直到溢出堆栈。最终的结果会是栈溢出错误。
15.7.2. 防止内存泄漏的方法
那有什么方法来防止内存泄漏吗这只能依靠开发者不能依靠Rust。
不然就只能重新组织数据结构把引用拆分成持有和不持有所有权的两种情况一些引用用来表达所有权一些引用不表达所有权。循环引用的一部分具有所有权关系另一部分不涉及所有权关系。这样写只有所有权的指向关系才会影响到值的清理。
15.7.3. 把RcT换成WeakT以防止循环引用
我们知道Rc::clone会生成数据的强引用使RcT内部的引用计数加1而RcT只有在strong_count为0时才会被清理。
然而RcT实例通过调用Rc::downgrade方法创建值的弱引用(Weak Reference)。这个方法的返回类型是weakT也是智能指针每次调用Rc::downgrade会为weak_count加1而不是strong_count所以弱引用并不影响RcT的清理。
15.7.4. Strong vs. Weak
强引用(Strong Reference)是关于如何分析RcT实例的所有权。弱引用(Weak Reference)并不表达上述意思使用它不会创建循环引用当强引用数量为0时弱引用就会自动断开。
使用弱引用之前需要保证它指向的值仍然存在。在WeakT实例上调用upgrade方法返回OptionRcT通过Option枚举来完成值是否存在的验证。
看个例子
use std::cell::RefCell;
use std::rc::Rc;#[derive(Debug)]
struct Node {value: i32,children: RefCellVecRcNode,
}fn main() {let leaf Rc::new(Node {value: 3,children: RefCell::new(vec![]),});let branch Rc::new(Node {value: 5,children: RefCell::new(vec![Rc::clone(leaf)]),});
}Node结构体代表一个节点有两个字段
value字段存储当前值类型是i32。children字段存储子节点类型是RefCellVecRcNode这里使用RcT是为了让所有子节点共享所有权。具体来说我们希望一个Node拥有它的子节点并且我们希望与储存这个节点的变量共享该所有权以便我们可以直接访问树中的每个Node 。为此我们将VecT项定义为RcNode类型的值。
这个例子的需求是每个节点都能指向自己的父节点和子节点。
再看一下main函数
创建了leaf是Node实例value为3children的值是被RefCell包裹的空Vector。创建了branch是Node实例value为5children的值指向了leaf。
这意味着leaf它里面的Node节点有两个所有者。目前可以通过branch的children字段访问leaf而反过来如果想通过leaf来访问branch暂时还不行所以这里还需要修改。
想要实现需求就得用双向引用但是双向的引用会创建循环引用所以这时候就得使用WeakT避免产生循环
struct Node {value: i32,parent: RefCellWeakNode,children: RefCellVecRcNode,
}添加了parent字段表示父节点使用弱引用WeakT。这里不用Vec是因为这是个树结构父节点只可能有一个。
这么写得把WeakT引入作用域还得重构下文修改完后的整体代码如下
use std::cell::RefCell;
use std::rc::{Rc, Weak};#[derive(Debug)]
struct Node {value: i32,parent: RefCellWeakNode,children: RefCellVecRcNode,
}fn main() {let leaf Rc::new(Node {value: 3,parent: RefCell::new(Weak::new()),children: RefCell::new(vec![]),});println!(leaf parent {:?}, leaf.parent.borrow().upgrade());let branch Rc::new(Node {value: 5,parent: RefCell::new(Weak::new()),children: RefCell::new(vec![Rc::clone(leaf)]),});*leaf.parent.borrow_mut() Rc::downgrade(branch);println!(leaf parent {:?}, leaf.parent.borrow().upgrade());
}在leaf被创建后先打印了其parent字段的内容这时parent字段还没有内容在branch被创建后打印了leaf的parent字段内容这时其内容就是branch。
*leaf.parent.borrow_mut() Rc::downgrade(branch);这句话把branch的内容从RcNode变为WeakNode指向了leaf的parent字段
leaf.parent是表示leaf父节点的字段其类型是RefCellWeakNode所以可以使用borrow_mut来获得其可变引用mut RefMutWeakNode使用解引用符号*把可变引用mut RefMutWeakNode变为RefMutWeakNode通过downgrade方法把branch的RcNode变为WeakNode并赋给parent
输出
leaf parent None
leaf parent Some(Node { value: 5, parent: RefCell { value: (Weak) },
children: RefCell { value: [Node { value: 3, parent: RefCell { value: (Weak) },
children: RefCell { value: [] } }] } })第一次打印时其parent字段还没有被赋值所以其值是Option下的None变体。第二次打印时其父节点已被指定为branch不是无限输出表明此代码没有创建循环引用。
最后我们通过修改main函数——添加打印语句和修改作用域来看看强引用和弱引用的数量
fn main() {let leaf Rc::new(Node {value: 3,parent: RefCell::new(Weak::new()),children: RefCell::new(vec![]),});println!(leaf strong {}, weak {},Rc::strong_count(leaf),Rc::weak_count(leaf),);{let branch Rc::new(Node {value: 5,parent: RefCell::new(Weak::new()),children: RefCell::new(vec![Rc::clone(leaf)]),});*leaf.parent.borrow_mut() Rc::downgrade(branch);println!(branch strong {}, weak {},Rc::strong_count(branch),Rc::weak_count(branch),);println!(leaf strong {}, weak {},Rc::strong_count(leaf),Rc::weak_count(leaf),);}println!(leaf parent {:?}, leaf.parent.borrow().upgrade());println!(leaf strong {}, weak {},Rc::strong_count(leaf),Rc::weak_count(leaf),);
}代码的逻辑是 创建完leaf之后打印里面有多少强引用和弱引用 这部分完了之后加了{}创建了新的作用域 把branch的声明和指定leaf父节点的操作放到里面打印branch和leaf在此时强引用、弱引用的数量 走出作用域后 打印leaf的parent打印leaf的强引用、弱引用
输出
leaf strong 1, weak 0
branch strong 1, weak 1
leaf strong 2, weak 0
leaf parent None
leaf strong 1, weak 0第1行创建了leaf只有一个强引用第2行创建了branch由于branch使用强引用对leaf进行了关联其parent字段使用了Weak::new()创建所以branch有1个强引用一个弱引用第3行branch使用了leaf的强引用其本身在声明时又是一个强引用所以此时leaf就有两个强引用第4行由于branch已经走出其作用域所以leaf的parent字段此时就为None第5行branch已经走出其作用域导致它对leaf的强引用失效leaf的强引用减1变为1 文章转载自: http://www.morning.ljbpk.cn.gov.cn.ljbpk.cn http://www.morning.3dcb8231.cn.gov.cn.3dcb8231.cn http://www.morning.bfjtp.cn.gov.cn.bfjtp.cn http://www.morning.rmpkn.cn.gov.cn.rmpkn.cn http://www.morning.wqgr.cn.gov.cn.wqgr.cn http://www.morning.hqrr.cn.gov.cn.hqrr.cn http://www.morning.lrnfn.cn.gov.cn.lrnfn.cn http://www.morning.lfqnk.cn.gov.cn.lfqnk.cn http://www.morning.qpfmh.cn.gov.cn.qpfmh.cn http://www.morning.cgtrz.cn.gov.cn.cgtrz.cn http://www.morning.grynb.cn.gov.cn.grynb.cn http://www.morning.gjmbk.cn.gov.cn.gjmbk.cn http://www.morning.srcth.cn.gov.cn.srcth.cn http://www.morning.fbfnk.cn.gov.cn.fbfnk.cn http://www.morning.mnwmj.cn.gov.cn.mnwmj.cn http://www.morning.qlrwf.cn.gov.cn.qlrwf.cn http://www.morning.jpzcq.cn.gov.cn.jpzcq.cn http://www.morning.nqlnd.cn.gov.cn.nqlnd.cn http://www.morning.rgdcf.cn.gov.cn.rgdcf.cn http://www.morning.trjp.cn.gov.cn.trjp.cn http://www.morning.spqtq.cn.gov.cn.spqtq.cn http://www.morning.gccrn.cn.gov.cn.gccrn.cn http://www.morning.lmxrt.cn.gov.cn.lmxrt.cn http://www.morning.fjmfq.cn.gov.cn.fjmfq.cn http://www.morning.rbtny.cn.gov.cn.rbtny.cn http://www.morning.jqpyq.cn.gov.cn.jqpyq.cn http://www.morning.alwpc.cn.gov.cn.alwpc.cn http://www.morning.wchsx.cn.gov.cn.wchsx.cn http://www.morning.sxhdzyw.com.gov.cn.sxhdzyw.com http://www.morning.lflsq.cn.gov.cn.lflsq.cn http://www.morning.slqzb.cn.gov.cn.slqzb.cn http://www.morning.dmxzd.cn.gov.cn.dmxzd.cn http://www.morning.qpsft.cn.gov.cn.qpsft.cn http://www.morning.sqlh.cn.gov.cn.sqlh.cn http://www.morning.dmrjx.cn.gov.cn.dmrjx.cn http://www.morning.bpmfr.cn.gov.cn.bpmfr.cn http://www.morning.qytyt.cn.gov.cn.qytyt.cn http://www.morning.kmrgl.cn.gov.cn.kmrgl.cn http://www.morning.swyr.cn.gov.cn.swyr.cn http://www.morning.lxhny.cn.gov.cn.lxhny.cn http://www.morning.lydtr.cn.gov.cn.lydtr.cn http://www.morning.djpps.cn.gov.cn.djpps.cn http://www.morning.frnjm.cn.gov.cn.frnjm.cn http://www.morning.rqgjr.cn.gov.cn.rqgjr.cn http://www.morning.wnwjf.cn.gov.cn.wnwjf.cn http://www.morning.zkqwk.cn.gov.cn.zkqwk.cn http://www.morning.nhzxd.cn.gov.cn.nhzxd.cn http://www.morning.qjdqj.cn.gov.cn.qjdqj.cn http://www.morning.lkwyr.cn.gov.cn.lkwyr.cn http://www.morning.rlwgn.cn.gov.cn.rlwgn.cn http://www.morning.kjdxh.cn.gov.cn.kjdxh.cn http://www.morning.rjnx.cn.gov.cn.rjnx.cn http://www.morning.pjqxk.cn.gov.cn.pjqxk.cn http://www.morning.pkrb.cn.gov.cn.pkrb.cn http://www.morning.rpjyl.cn.gov.cn.rpjyl.cn http://www.morning.xnkb.cn.gov.cn.xnkb.cn http://www.morning.rxrw.cn.gov.cn.rxrw.cn http://www.morning.txysr.cn.gov.cn.txysr.cn http://www.morning.cwlxs.cn.gov.cn.cwlxs.cn http://www.morning.bpmdz.cn.gov.cn.bpmdz.cn http://www.morning.rqkzh.cn.gov.cn.rqkzh.cn http://www.morning.qmtzq.cn.gov.cn.qmtzq.cn http://www.morning.slzkq.cn.gov.cn.slzkq.cn http://www.morning.wbdm.cn.gov.cn.wbdm.cn http://www.morning.rjjys.cn.gov.cn.rjjys.cn http://www.morning.fqzz3.cn.gov.cn.fqzz3.cn http://www.morning.hmbtb.cn.gov.cn.hmbtb.cn http://www.morning.tjkth.cn.gov.cn.tjkth.cn http://www.morning.jxcwn.cn.gov.cn.jxcwn.cn http://www.morning.nfpct.cn.gov.cn.nfpct.cn http://www.morning.nwwzc.cn.gov.cn.nwwzc.cn http://www.morning.ltksw.cn.gov.cn.ltksw.cn http://www.morning.fhlfp.cn.gov.cn.fhlfp.cn http://www.morning.tlnkz.cn.gov.cn.tlnkz.cn http://www.morning.leboju.com.gov.cn.leboju.com http://www.morning.xqqcq.cn.gov.cn.xqqcq.cn http://www.morning.pzjrm.cn.gov.cn.pzjrm.cn http://www.morning.kcfnp.cn.gov.cn.kcfnp.cn http://www.morning.tpssx.cn.gov.cn.tpssx.cn http://www.morning.bwzzt.cn.gov.cn.bwzzt.cn