Rust 智能指针(一)

1.Box<T>

Box<T>是指向堆中的指针。

fn main() {
let box = Box::new(3);
println!("{}", box);
}

在出了指针的作用域之后,指针和它指向的对象都将被释放。

在本例中,box将在main函数之后被释放。

由于Box<T>的大小是确定的(size类型的大小),所以可以使用Box编写嵌套类型,比如实现链表。

2.Deref trait

实现Deref这个trait可以重载解引用运算符(*),这样可以把Deref trait当作普通引用。

use std::ops::Deref;

fn main() {
let b=MyBox::new(12);
assert_eq!(*b,12);
} struct MyBox<T>(T); impl<T> MyBox<T> {
fn new(value: T) -> Self {
MyBox(value)
}
} impl<T> Deref for MyBox<T> {
type Target = T; fn deref(&self) -> &Self::Target {
&self.0
}
}

当调用*b时,本质上是*(b.deref()),这样&引用和Deref引用的形式就统一了。

函数和方法的隐式解引用强制多态

假设我们有一个函数,它需要一个&str类型的参数。

fn print_name(name: &str){
println!("name:{}",name);
}

改变main中的代码

let string = MyBox::new(String::from("My Box"));
print_name(&(*string))

*string获得 String 类型,调用String类型的&来获取&str类型(可以查看标准库,实现了AsRef<str> trait)。

如果没有隐式解引用强制多态,我们需要这么写代码。很明显,这种写法太啰嗦了,本来rust的符号一大堆,现在这样子根本无法忍受。

我们稍微更改一下

print_name(&string);

其他代码不变,把参数改为&string,明显,这是获取一个&MyBox<String>的对象,然后rust会自动调用deref()转为&String&String调用deref()转为&str(String也实现了Deref trait),这样子就与函数签名匹配了,编译通过。

也就是,rust会隐式解引用来匹配所声明变量(参数)的类型。

let a:&str = &string;
println!("{}", a);

这样的代码也是有效的。

Rust 在发现类型和 trait 实现满足三种情况时会进行解引用强制多态:

  • T: Deref<Target=U> 时从 &T&U
  • T: DerefMut<Target=U> 时从 &mut T&mut U
  • T: Deref<Target=U> 时从 &mut T&U

Deref trait 解引用为 &T ,即不可变引用, 而 DerefMut trait 解引用为 &mut T,是可变引用。

3.Drop trait

Drop是专门用来进行一些资源释放的操作,比如IO操作,当对象离开作用域时,会自动调用 Dropdrop 方法来释放资源。

use std::fmt::Display;

fn main() {
let mb=MyBox::new(2);
println!("the end");
} struct MyBox<T:Display>(T); impl<T:Display> MyBox<T> {
fn new(value: T) -> Self {
MyBox(value)
}
}
impl<T:Display> Drop for MyBox<T>{
fn drop(&mut self) {
println!("the data is {}",self.0);
}
}

泛型约束T:Display是为了让它能够被打印。这段代码最终输出

the end
the data is 2

提前释放资源

有时候,我们需要提前释放资源。比如写入文件完成后,需要立马 close 。但是,Drop::drop 是不允许手动调用的,这时,我们需要 std::mem::drop 函数来释放。

修改main函数

fn main() {
let mb=MyBox::new(2);
drop(mb);
println!("the end");
}

输出结果

the data is 2
the end

这表明,Drop::drop被提前调用了,并且只调用了一次。

注意 std::mem::drop 的参数是 move 语义,也就是说,在调用 std::mem::drop 之后,mb 已经被移动,不能够再用了。

那么这个函数是怎么实现的呢?我们跳转到 drop 的实现

#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn drop<T>(_x: T) { }

对,它的函数体是空的!!!

其实不难理解,因为 mb 被移动到 drop 中了,在 drop 函数结束后,mb.drop() 就会被调用 ,这样就实现了资源的提前释放。

Rust 智能指针(一)的更多相关文章

  1. 探讨 Rust 智能指针 | Vol.17

    分享主题:<探讨 Rust 智能指针>| Vol. 17 分享讲师:苏林 分享时间: 周日晚上 2021-11-14 20:30-21:30 腾讯会议地址: https://meeting ...

  2. Rust 智能指针(二)

    1. Rc<T> 引用计数指针 Rc<T> 是引用计数指针,可以使用clone使得指针所指向的数据具有多个所有者. enum List { Cons(i32, Rc<Li ...

  3. Rust入坑指南:智能指针

    在了解了Rust中的所有权.所有权借用.生命周期这些概念后,相信各位坑友对Rust已经有了比较深刻的认识了,今天又是一个连环坑,我们一起来把智能指针刨出来,一探究竟. 智能指针是Rust中一种特殊的数 ...

  4. [易学易懂系列|rustlang语言|零基础|快速入门|(21)|智能指针]

    [易学易懂系列|rustlang语言|零基础|快速入门|(21)|智能指针] 实用知识 智能指针 我们今天来讲讲Rust中的智能指针. 什么是指针? 在Rust,指针(普通指针),就是保存内存地址的值 ...

  5. 转:C++ 智能指针的正确使用方式

    转:https://www.cyhone.com/articles/right-way-to-use-cpp-smart-pointer/#comments C++11 中推出了三种智能指针,uniq ...

  6. c++11新特性实战(二):智能指针

    c++11添加了新的智能指针,unique_ptr.shared_ptr和weak_ptr,同时也将auto_ptr置为废弃(deprecated). 但是在实际的使用过程中,很多人都会有这样的问题: ...

  7. enote笔记法使用范例(2)——指针(1)智能指针

    要知道什么是智能指针,首先了解什么称为 “资源分配即初始化” what RAII:RAII—Resource Acquisition Is Initialization,即“资源分配即初始化” 在&l ...

  8. C++11 shared_ptr 智能指针 的使用,避免内存泄露

    多线程程序经常会遇到在某个线程A创建了一个对象,这个对象需要在线程B使用, 在没有shared_ptr时,因为线程A,B结束时间不确定,即在A或B线程先释放这个对象都有可能造成另一个线程崩溃, 所以为 ...

  9. C++智能指针

    引用计数技术及智能指针的简单实现 基础对象类 class Point { public: Point(int xVal = 0, int yVal = 0) : x(xVal), y(yVal) { ...

随机推荐

  1. mysql 免安装版

    通过MySQL安装程序(.msi文件)来安装虽然简洁高效,但不够灵活,所以我们这里介绍免安装版. 1.  下载: 进入官网-->Downloads-->Community(社区版)--&g ...

  2. gitlab的仓库迁移到新的gitlab

    1.下载原有gitlab源码 git clone http://gitlab.**.com/projectName gitlab地址替换成为新gitlab地址 git remote set-url o ...

  3. Spring手册

    一.Spring 简介 二.结构体系 三.七大主要模块 四.Spring Maven依赖 五 .Sprinf framework 一.Spring 简介 spring是一个开源的轻量级的应用开发框架, ...

  4. 转:Eclipse+webservice开发实例

    原文地址:http://blog.csdn.net/xw13106209/article/details/7049614 1.参考文献: 1.利用Java编写简单的WebService实例  http ...

  5. Office 365实现单点登录系列(5)—配置单点登录

    这是单点登录系列的最后一篇文章,前面4篇文章其实都是在为这篇文章的内容做准备,我把这四篇文章的链接放在下面,如果大家有需要,可以参考我以下的链接: Office 365实现单点登录系列(1)—域环境搭 ...

  6. 阿里云堡垒机密钥连接ECS服务器

    文:铁乐与猫 2017-6月中旬 堡垒机远程桌面windows系统就不用细说了 堡垒机远程ssh连接linux系统倒要说一下,毕竟是为安全一般只用通过密钥连接,而不使用密码的方式连接. 首先我们得在需 ...

  7. VMware下 CentOS 连接外网问题(笔记)

    虚拟机连接外网有三种模式.桥接.Nat.Host-Only.三者的区别,详见 实例讲解虚拟机3种网络模式(桥接.nat.Host-only) 使用虚拟机连接外网时,一定要充分考虑本地的网络环境!!! ...

  8. ZT Android 4.2 BT系统之蓝牙关闭过程全跟踪

    Android 4.2 BT系统之蓝牙关闭过程全跟踪 分类: android 2013-08-03 00:34 2252人阅读 评论(10) 收藏 举报 代码位置:       frameworks/ ...

  9. 字典 & 列表表达式 结合

    题: 思路: 要求的结果是小字典里面的两个值组成的列表,所以只要抓到小字典,这个题就可以用列表推导式直接表达了.所 以把小字典设为元素d,然后用d在列表里面遍历,列表呢,是大字典的一个值. 答案:  

  10. codeforces 1007B Pave the Parallelepiped

    codeforces 1007B Pave the Parallelepiped 题意 题解 代码 #include<bits/stdc++.h> using namespace std; ...