深圳做网站公司有那些百度网址大全网站大全
- 作者: 五速梦信息网
- 时间: 2026年04月20日 09:19
当前位置: 首页 > news >正文
深圳做网站公司有那些,百度网址大全网站大全,08影院 WordPress模板,南昌网站建设模板总部一、堆和栈
栈和堆都是程序运行时使用的内存#xff0c;但是它们的结构不同。
1.栈 栈#xff0c;英文是stack。是内存的一段区域。 栈是后进先出形式的。就像薯片桶#xff0c;先放进去的一片只能后拿出来。 栈上存储的数据大小必须是已知且固定的。也就是说如果一个变量…一、堆和栈
栈和堆都是程序运行时使用的内存但是它们的结构不同。
1.栈 栈英文是stack。是内存的一段区域。 栈是后进先出形式的。就像薯片桶先放进去的一片只能后拿出来。 栈上存储的数据大小必须是已知且固定的。也就是说如果一个变量或数据要放到栈上那么它的大小在编译是就必须是明确的。 例如类型为i32的变量它的大小是固定4个字节。
2.堆 堆英文是heap。是内存的另一段区域。堆内存也叫做资源。 堆是缺乏组织的当向堆放入数据时你要请求一定大小的空间。内存分配器在堆的某处找到一块足够大的空位把它标记为已使用并返回一个表示该位置地址的指针。这个过程称作在堆上分配内存。因为指针大小是已知且固定的所以可以将该指针存储在栈上不过当需要实际数据时必须去指针指向的内存读取数据。就像一个围棋棋盘你可以把一枚棋子放到任意可以放得下的位置。 在编译时大小未知或大小可能变化的数据要存储在堆上。 堆不受系统管理由用户自己管理因此使用不当内存溢出的可能性就大大增加了。
Rust与其他语言的区别 1指针超出作用域会自动释放堆内存 对于简单类型的栈内存如int超出作用域后自动释放这个功能各个语言都有。而对于new出来的堆内存在c/c中要手动释放在java中要委托垃圾回收释放。而垃圾回收不是实时的会影响性能手动释放又总会有人忘记释放。而Rust对栈内存和堆内存一视同仁超出作用域一律自动释放相当于自动delete指针。所以rust避免了内存泄漏。 在作用域结束时释放资源的模式称作资源获取即初始化Resource Acquisition Is Initialization (RAII)。 rust强制使用raii所以任何对象在离开作用域时它的析构函数就被调用然后它占有的资源就被释放。 这避免了资源泄漏所以你再也不用手动释放内存或者担心内存泄漏。 2所有权 某段内存只能被最后的变量名所有前面声明过的变量都作废这样一段内存就只有一个所有者只有所有者可以释放这块内存。这有效避免了被多个变量释放的问题而且该操作是在编译期的这可在编译期就能避免空指针问题。比如c中a和b指向同一块内存如果delete a之后再delete b就会出错而rust中不会出现这种问题。
二、所有权
一所有权是什么 所有权是指对内存资源的控制权和管理权。 在Rust中每个值都有一个唯一的所有者。定义一个变量就是声明这个值由这个变量所有。所有的值最终都要存储在一块内存上变量拥有这个值其实是拥有这块内存。栈内存所有者就是声明时的变量而堆内存所有者是分配返回的指针。 只有所有者才能释放这块内存其他人不能释放这块内存。 当所有者超出作用域时会自动释放这块内存。
所有权的规则 1.Rust中的每一个值都有一个所有者。 2.值在任一时刻有且只有一个所有者。 3.当所有者离开作用域这个值将被丢弃。
比如 现在可以把Box当成一个指针后面章节再讲解Box用法。
fn create_box() {let _box1 Box::new(3i32);// 在堆上分配一个整型数据// _box1 在这里被销毁内存得到释放。如果是c就得手动delete否则就会内存泄漏。这就是区别。
}
fn main() {let _box2 Box::new(5i32);// 在堆上分配一个整型数据// 嵌套作用域{let _box3 Box::new(4i32);// 在堆上分配一个整型数据// _box3 在这里被销毁内存得到释放}// 创建一大堆 box 完全不需要手动释放内存for _ in 0u32..1000 {create_box();}// _box2 在这里被销毁内存得到释放
}二转让所有权 所有权可以转让。转让所有权也叫move。 就是由新变量拥有内存旧变量变成无效的。
s1转让给s2就像下图所示。s2拥有堆内存s1变无效。
Rust语言中转让所有权的方式有以下几种 1.把一个变量赋值给另一个变量。 2.把变量值传递给函数作为参数。 3.函数中返回一个变量作为返回值。
1.把一个变量赋值给另一个变量
fn main(){let a Box::new(5i32);// a 是一个指向堆分配的整数的指针let b a;// 移动a到b把a的指针地址而非数据复制到b。现在是b拥有堆内存a变无效。//println!(a contains: {}, a);// 报错a无效因为它不再拥有那部分堆上的内存。
}2.把变量值传递给函数作为参数。 值传递方式值的所有权也会发生变更
fn destroy_box(c: Boxi32) {println!(Destroying a box that contains {}, c);// c 被销毁且内存得到释放
}
fn main() {let a Box::new(5i32);// a 是一个指向堆分配的整数的指针destroy_box(a);// a的所有权转移给函数形参a变无效//println!(a contains: {}, a);// 报错a无效
}3.函数中返回一个变量作为返回值 函数的形参获得的所有权将在离开函数后就失效了。失效的数据就再也访问不到了。 为了解决所有权失效的问题我们可以让函数将所有者返回给调用者。
fn destroy_box(c: Boxi32) -Boxi32 {println!(Destroying a box that contains {}, c);c
}
fn main() {let mut a Box::new(5i32);// a 是一个指向堆分配的整数的指针a destroy_box(a);// a的所有权转移给函数形参a变无效println!(b contains: {}, a);// 报错a无效
}三复刻 复刻英文是clone。也叫深复制或深拷贝。 有时候我们需要创建一个值的完全独立的副本而不是转让所有权。在这种情况下可以使用复刻。
创建s1的副本s2就像下图所示。s1和s2都拥有了独立的所有权。
示例
fn main() {let s1 String::from(hello);let s2 s1.clone();println!({} {}, s1, s2); // 正常打印 hello hello
}创建了字符串hello的副本赋值给s2因此s1和s2都拥有了独立的所有权。
fn main() {let a Box::new(5i32);let b a.clone();println!({}, a);println!({}, b);
}栈上的数据 看下例
fn main() {let a 50;let b a;println!({}, a);println!({}, b);
}这段代码能编译通过。按照所有权转让规则的话它应该编译错误才对可是为什么能编译通过 因为像整型这样的类型完全存储在栈上并不需要占用那么大的内存所以拷贝它的值是很快的。没有理由在创建变量b后使a无效。这里没有深浅拷贝的区别所以这里不管是否调用clone效果都一样。 Rust有一个Copy trait可以用于存储在栈上的类型。如果一个类型实现了Copy trait那么就不使用所有权转让而是使用复刻。
那么哪些类型实现了Copy trait呢 Rust不允许自身或其部分实现了Drop trait的类型使用Copy trait。 任何简单标量值的组合都可以实现Copy任何不在堆上分配内存的类型都可以实现Copy。 如下是一些Copy的类型 1.布尔类型bool 2.数字类型包括整数和浮点数比如 u32f64。 3.字符类型char 4.元组当且仅当其包含的类型都实现Copy的时候。比如(i32, i32) 实现了Copy但 (i32, String) 就没有。
- 上一篇: 深圳做网站费用深圳龙岗网络
- 下一篇: 深圳做网站联系电话西安建设工程交易信息网
相关文章
-
深圳做网站费用深圳龙岗网络
深圳做网站费用深圳龙岗网络
- 技术栈
- 2026年04月20日
-
深圳做网站多钱wordpress付费观看
深圳做网站多钱wordpress付费观看
- 技术栈
- 2026年04月20日
-
深圳做网站的公司那个好东莞智通人才网招聘信息网
深圳做网站的公司那个好东莞智通人才网招聘信息网
- 技术栈
- 2026年04月20日
-
深圳做网站联系电话西安建设工程交易信息网
深圳做网站联系电话西安建设工程交易信息网
- 技术栈
- 2026年04月20日
-
深圳做网站三网合一网页和网站有什么关系
深圳做网站三网合一网页和网站有什么关系
- 技术栈
- 2026年04月20日
-
深圳做网站最好的公工信和信息化部网站
深圳做网站最好的公工信和信息化部网站
- 技术栈
- 2026年04月20日
