面向C++程序员的Rust教程(二)

本文探讨了Rust语言中所有权和移动语义的独特之处,与C++的复制和浅复制进行对比,强调了Rust的移动语义是所有权转移而非复制,以及借用概念在避免内存问题中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先序文章请看:
面向C++程序员的Rust教程(一)

所有权与移动语义

要说Rust语言跟其他语言最大的区别,那笔者觉得非数这个所有权和移动语义莫属。

深浅复制

对于绝大多数语言来说,变量/对象之间的赋值通常都是复制语义。例如C++中:

void Demo() {
   
   
  Obj o1; // 对象1
  auto o2 = o1; // 复制语义,o2是o1的复制
}

只不过深复制还是浅复制需要进一步研究。C++中由于完全支持栈上部署自定义类型以及自定义的拷贝构造/赋值函数,程序员需要自行判断内部指针/引用关系,决定使用深复制或是浅复制。

一些语言是把「结构体」和「类」做区分,结构体仅用于做数据聚合,部署在栈上,而类则添加更多OO特性,部署在堆上(然后栈上给一个指针)。比如说Swift和C#就是如此。那么这种情况下栈上部署的类型,复制就为深复制,而堆上部署的类型复制就为浅复制。

还有一些语言索性不允许自定义类型在栈上部署(比如java、OC),那么这种情况下也就是限定了默认的复制均为浅复制,例如下面OC的例子:

void Demo() {
   
   
  Object *o1 = [[Object alloc] init];
  Object *o2 = o1; // 由于栈上只有指针,因此复制一定是浅复制
}

总之,统一的原则都是「栈上做深复制」,所以如果栈上是完整数据那么就是深复制,如果栈上只有指针/引用,那么就是浅复制。

rust移动语义

但Rust非常特殊,他根本不在这里纠结深复制还是浅复制的问题,而Rust默认为「移动语义」而非「复制语义」。当然,这只针对自定义类型来说,对于整数、浮点数这些它仍然是简单的值复制。我们来看一个例子:

fn main() {
   
   
  let mut a = 5;
  let b = a;
  a = 10;
  println!("{},{}", a, b); // 10,5
}

这种基本类型看上去无可厚非,但如果换成自定义类型结果可能大大超出预期:

struct Test {
   
   
  a: i32,
  b: i32
}

fn main() {
   
   
  let mut t = Test{
   
   a: 1, b: 2};
  let t2 = t;
  t.a = 8; // ERROR
}

我们会发现,在尝试更改t.a的时候,编译报错了,报错信息如下:

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

borehole打洞哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值