起因
今天学习一下Rust中的指针.
原生指针
//原生指针 *const (不可变) 和 *mut(可变)
let mut x = 32;
let y = &mut x; //引用
unsafe {
*y =64; //通过原生指针 修改值
}
引用
//引用 通过&和&mut
let a = 100;
let b = &a;
println!("a={}", b);
智能指针
智能指针最早在c++得到了应用.智能指针是RAII(资源获取即初始化)和作用域范围的完美结合,在离开所在作用域的范围的进行资源的释放.
#ifndef ALGORITHM_MYCLASS_H
#define ALGORITHM_MYCLASS_H
#include <iostream>
using namespace std;
class MyClass
{
public:
char* p;
MyClass()
{
cout << "调用构造函数" << endl;
p = new char[1024 * 1024 * 100](); //在堆上分配100m的空间
}
~MyClass()
{
cout << "调用析构函数" << endl;
delete[] p; //在析构函数时,释放100m空间
}
};
#endif //ALGORITHM_MYCLASS_H
int main(int argc, char *argv[]) {
{
vector<int> vec1{1, 2, 3}; //①在任务管理器中看当前程序所占内存大小
unique_ptr<MyClass> myClass(new MyClass()); //unique_ptr 智能指针 在离开所在的作用域,自动释放资源
vector<int> vec2{1, 2, 3}; //②在任务管理器中看当前程序所占内存大小
}
cin.get(); //③任务管理器中看当前程序所占内存大小,
//得出结论: 通过智能指针给myClass在堆上进行内存分配,在离开所在的作用域后,自动调用析构函数,并释放资源
return 0;
}
进入正题,Rust中最典型的智能指针非Box和String莫属,String使用最多,Rust中的智能指针都会实现Drop(没实现Drop,不会自动释放资源,能叫智能)和Deref(没有*,能叫指针),在Rust中类型默认是分配栈上的,可以通过Box(有点像C#的装箱操作,在IL中使用box进行装箱操作)分配到堆上.具体看下面的示例代码:
#[derive(Debug)]
struct MyPoint
{
x:i32,
y:i32,
}
//这里只是打印是否调用drop
impl Drop for MyPoint {
fn drop(&mut self) {
println!("drop MyPoint x={} y={}", self.x,self.y);
}
}
fn main() {
{
let p1 = MyPoint { x: 1 }; //是在栈上进行的内存分配
{
let point = Box::new(MyPoint { x: 1 }); //通过Box的new函数在堆上开辟内存空间
println!("MyPoint x={}",a.x);
}
//Box实现Drop trait在离开所在作用域自动内存
}
}
Box<T>源码,只有new/drop/deref.
/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
#[lang = "owned_box"] //编译器实现内存分配和释放 由于实现drop trait可以自动释放资源
#[fundamental]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Box<T: ?Sized>(Unique<T>);
impl<T> Box<T> {
/// Allocates memory on the heap and then places `x` into it.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline(always)]
pub fn new(x: T) -> Box<T> {
box x //box 在编译时,由编译器将box替换为exchange_malloc在离开作用域的是调用drop
}
}
#[stable(feature = "rust1", since = "1.0.0")]
unsafe impl<#[may_dangle] T: ?Sized> Drop for Box<T> {
fn drop(&mut self) {
// FIXME: Do nothing, drop is currently performed by compiler.
//由编译器生成 释放资源代码
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Box<T> {
type Target = T;
fn deref(&self) -> &T {
&**self
}
}
通过Rust编译器rustc,生成汇编代码,是可以看到exchange_malloc函数的,具体看下边生成的代码:
//通过--emit 可以指定 asm(汇编) llvm-ir(llvm中间代码) obj(目标文件)
rustc --emit asm .\test.rs
个人能力有限,如果您发现有什么不对,请私信我
如果您觉得对您有用的话,可以点个赞或者加个关注,欢迎大家一起进行技术交流