Rust编程-高级特性

unsafe:内存不安全

        内存安全问题,例如空指针解引用

        关键字unsafe来切换到不安全模式,并在被标记后的代码块中使用不安全代码

                使用unsafe告诉编译器后面代码安全性自行负责

                因为电脑硬件安全问题,必须编写可能不安全的代码

可以将不安全代码封装在一个安全的抽象中并提供一套安全的API,防止unsafe代码泄漏到任何调用它的地方,因为使用安全抽象总会是安全的。

        不安全Rust允许你执行4种在安全Rust中不被允许的操作:

                解引用裸指针:

                        裸指针 (raw pointer):裸指针要么是可变的,要么是不可变的,它们分别被写作*const T和*mut T(固定写法)。

                        星号是类型名的一部分而不是解引用操作。

                        裸指针:(使用裸指针的好处是可以规避Rust的引用规则

                                使用as语法创建裸指针,并且创建裸指针不需要unsafe关键字

                                允许忽略借用规则,可以同时拥有指向同一个内存地址的可变和
不可变指针,或者拥有指向同一个地址的多个可变指针。

                                不能保证自己总是指向了有效的内存地址。

                                允许为空

                                没有实现任何自动清理机制

                                使用裸指针的目的:要用途便是与C代码接口进行交互

                调用不安全的函数或方法:

                        不安全函数(unsafe function),在定义前面要标记unsafe

                        单独的unsafe代码块中调用不安全的函数

                        你可以在一个不安全函数中执

行其他不安全操作而无须添加额外的unsafe代码块

                        创建不安全代码的安全抽象:

                                将不安全代码封装在安全函数中是一种十分常见的抽象。

                                代码中如果需要两次可变引用,那么就可以考虑使用裸指针:

                                        as_mut_ptr方法来访问切片包含的裸指针

                                        slice::from_raw_parts_mut函数接收一个裸指针和长度来创建一个切片

                                        ptr.offset()方法也是不安全的

fn split_at_mut(slice:&mut [i32],mid:usize)->(&mut [i32],&mut [i32]){
  let len = slice.len();
  let ptr = slice.as_mut_ptr();// 可变指针
  assert!(mid<=len);

  unsafe{
    (slice::from_raw_parts_mut(ptr,mid),slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))   
  }

        使用裸指针关键是可以确认unsafe代码块中的裸指针都会指向有效的切片数据且不会产生任何的数据竞争

                使用extern函数调用外部代码(另一种语言)      

                        extern关键字, 简化创建使用外部函数的接口

                        任何在extern块中声明的函数都是不安全的。

                        

extern "C"{
  fn abs(iput:i32) -> i32;
}

        声明在另一种语言中定义的函数 。"C"指明了外部函数使用的应用二进制接口 (Application
Binary Interface,ABI):它被用来定义函数在汇编层面的调用方式。我们使用的"C"ABI正是C编程语言的ABI,它也是最常见的ABI格式之。

        可以使用extern来创建一个允许其他语言调用Rust函数的接口。

        

#[no_mangle]
pub extern "C" fn call_from_c() {
println!("Just called a Rust function from C!");
}

 #[no_mangle] 告诉编译器不允许修改函数名

 在“C”ABI后面指定函数名。这段代码可以被C语言使用

        访问或修改可变的静态变量

        如果两个线程同时访问一个可变的全局变量,那么就会造成数据竞争。

        全局变量也被称为静态 (static)变量

        静态变量的名称会约定俗成地被写作SCREAMING_SNAKE_CASE

        要标注变量的类型,例如&'static str,静态变量只能存储拥有'static生命周期的引

        常量和不可变静态变量:静态变量的值在内存中拥有固定的地址,使用它的值
总是会访问到同样的数据;常量则允许在任何被使用到的时候复制其数据。

        访问和修改可变的静态变量是不安全的

        实现不安全trait:

                trait定义的前面加上unsafe关键字,该trait也只能在unsafe代码块中实现

总结:unsafe关键字能够帮助轻松定位问题

tait的关联类型:       

        定义出包含某些类型的trait,而无须在实现前确定它们的具体类型是什么 

        

pub trait Iterator{
  type Item;
  fn next(&mut self) -> Option<Self::Item>;
}

impl Iterator for Counter {
type Item = u32;
fn next(&mut self) -> Option<Self::Item> {
}

     Item就是trait的关联类型。关联类型和泛型很像

       泛型版本: 

pub trait Iterator<T> {
fn next(&mut self) -> Option<T>;
}

        使用泛型,需要在每次使用的时候指明泛型的具体类型:

泛型也可以指明其他类型,这样Counter就拥有多个不同版本的Iterator实现

impl Iterator<String> for Counter

  在调用next的时候也必须指明具体的泛型类型

   而使用关联类型:

impl Iterator for Counter

    不用每次都指定是哪种关联类型,一次指定关联类型即可。

        默认泛型参数和运算符重载

        <PlaceholderType=ConcreteType>来为泛型指定默认类型。 

        运算符重载自定义运算符(比如+)的具体行为。       

        完全限定语法

        Rust既不会阻止两个trait拥有相同名称的方法,也不会阻止你为同一个类型实现这样的两个trait。但是使用时需要具体指明调用的具体对象。

        调用同名函数:

 let person = Human;
  Pilot::fly(&person);
  Wizard::fly(&person);

,然后传入实例的引用,因为函数的第一个参数是self;

那么对于关联函数,第一个参数不是self:

        完全限定访问语法:

                <Dog as Animal>::baby_name()

        超trait(super trait):

                在一个trait中使用另外一个trait的功能

                

trait OutlinePrint: fmt::Display{
}

        表明trait OutlinePrint依赖fmt::Display

        

  • 9
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值