Rust 02.控制、引用、切片Slice、智能指针

1.控制流

rust 复制代码
//rust通过所有权机制来管理内存,编译器在编译就会根据所有权规则对内存的使用进行
//堆和栈
//编译的时候数据的类型大小是固定的,就是分配在栈上的
//编译的时候数据类型大小不固定,就是分配堆上的
fn main() {
    let x: i32 = 1;

    {
        let y: i32 = 1;
        println!("x = {}", x);
        println!("y = {}", y);
    }

    {
        let s1 = String::from("hello");
        //s1.push_str(" world");
        println!("s1 = {}", s1); //String类型离开作用域的时候会调用drop方法

        let s2 = s1; //浅拷贝 只是拷贝了指针, 数据并没有拷贝
        println!("s2= {}", s2);
        //println!("s1= {}", s1); //s1在被copy后会自动释放指针内存,所以会报错
        

        //clone 深拷贝数据
        let s3 = s2.clone();
        println!("s3= {}", s3);
        println!("s2= {}", s2);
    }

控制权

rust 复制代码
fn takes_ownership1(some_string: String){
    println!("{}", some_string);
}

fn takes_ownership2(some_string: String) -> String{
    println!("{}", some_string);
    some_string
}

fn makes_copy(i: i32) {
    println!("i = {}", i);
}

fn main() {
    let s = String::from("hello");
    //takes_ownership1(s); //s在调用函数后被drop,后续无法打印其值
    //println!("{}", s);
    let s2 = takes_ownership2(s);
    println!("{}", s2);

    let x = 5;
    makes_copy(x);
    println!("{}", x);
    println!("Hello, world!");
}

2.引用

rust 复制代码
//引用: 用法&,
//让我们创建一个指向值的应用,但是并不拥有它,因为不拥有这个值,所以,当引用离开其值指向的作用域后也不会被丢弃
fn calcute_length(s: &String) ->usize {
    s.len()
}

//借用:&mut 可以修改字符串,同时不会执行drop操作
fn modify_s(s: &mut String) {
    s.push_str(", world");
}

fn dangle() -> &String {
    let s = String::from("hello");
    &s
}

fn main() {
    let mut s1 = String::from("hello");
    
    //在任意给定时间,有了可变引用之后不能再有不可变引用
    let r1 = &s1;
    let r2 = &s1;
    println!("{}, {}", r1, r2);

    let r3 = &mut s1;
    r3.push_str(", world");
	//println!("{}, {}", r1, r2); 由于r3为 可变引用, r1,r2不能在这里使用,必须在r3之前使用
		
    //引用不能为空,dangle()中给s赋值结束后就drop了,最终返回了空指针,这是不合法的
    //let ref_s = dangle();
    //println!("{}", ref_s);
}

3.Slice

rust 复制代码
//1、字符串slice是String中一部分值的引用
//2、字面值就是slice
//3、其它类型slice
fn main() {
    let s = String::from("hello world");

    let h = &s[0..5]; 	//区间[0,5)
    let h = &s[0..=4]; 	//区间[0,4]
    let h = &s[..=4]; 	//区间[0,4]
    let h = &s[..5]; 	//区间[0,5)
    println!("h = {}", h);

    let w = &s[6..11];  //区间[6,11)
    let w = &s[6..=10]; //区间[6,10]
    let w = &s[6..];  	//区间[6,s.len())
    let w = &s[..]; 	//区间[0,s.len())
    println!("w = {}", w);

    //let ss = String::from("你好");
    //let w1 = &ss[0..1];

    let a = [1, 2, 3, 4];	
    let sss = &a[1..3];		//取a中[1,3)的元素
    println!("sss = {}", sss[0]);	//a[1]
    println!("sss = {}", sss[1]);	//a[2]
    println!("len = {}", sss.len());	//长度为2
}

4.智能指针

Box
rust 复制代码
fn main() {
    let text: String = "Hello CSDN".to_string();
    // 将字符串移动到堆上 
    let box_text: Box<String> = Box::new(text);
    // 此时原text已失效,因为所有权已经转移给box_text
    println!("{}", box_text);
}
Rc
rust 复制代码
use std::rc::Rc;
 
fn main() {
	//  Rc<T>提供了非独占、可共享的引用,它的内部维护了一个引用计数。当引用数量变为0时,会自动释放堆内存。
    let shared_data = Rc::new(66);
 
    // 创建指向同一数据的多个Rc实例
    let ref1 = Rc::clone(&shared_data);
    let ref2 = Rc::clone(&shared_data);
 
    println!("ref1: {}", ref1);
    println!("ref2: {}", ref2);
 
    // 当最后一个Rc实例超出作用域时,数据会被清理
}
相关推荐
fengxin_rou1 分钟前
黑马点评项目万字总结:从redis基础到实战应用详解
java·开发语言·分布式·后端·黑马点评
zhouwy1133 分钟前
Golang 基础与实战笔记:从语法到微服务的全面指南
开发语言·go
灰子学技术4 分钟前
Envoy TCP 层面的 Metric 指标分析
开发语言·网络·网络协议·tcp/ip·php
清水白石00815 分钟前
生成器不是性能银弹:什么时候该用 `yield` 省内存,什么时候它会拖慢 Python 数据处理吞吐?
开发语言·python·原型模式
不甘先生17 分钟前
Go context 实战指南:从入门到生产级并发控制(架构师避坑手册)
开发语言·后端·golang
AI进化营-智能译站18 分钟前
ROS2 C++开发系列18-STL容器实战:deque缓存激光雷达数据|priority_queue调度任务
开发语言·c++·缓存·ai
初心未改HD32 分钟前
Go 泛型完全指南:从入门到实战
开发语言·golang
salipopl33 分钟前
Spring Boot 整合 Druid 并开启监控
java·spring boot·后端
西红柿炒番茄3136 分钟前
【Python】一个自动切换壁纸的python程序
开发语言·python
ShiJiuD66688899939 分钟前
JSP Cookie和Session
java·开发语言