• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

# 杂记rust的destructuring binding(反结构化绑定)与ownership(所有权)

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

起因

rust by example看得我想睡觉...突然遇到个关于反结构化绑定的奇怪的特性:

struct Pair(Box<i32>, Box<i32>);

impl Pair {
    fn destroy(self) {
        let Pair(first, second) = self;
        println!("Destroying Pair({}, {})", first, second);
    }
}

fn main() {
    let pair = Pair(Box::new(1), Box::new(2));

    pair.destroy();
    pair.destroy();
}

对pair调用两次destroy()方法居然会得到错误,代码注释提示let语句会消耗self,导致self内容被move(移动):

let Pair(first, second) = self;
// 这里self不再可见

以前听说过rust的lifetime,ownership,看着样子估计就是这方面的问题导致的特性

尝试

我大概理解了它的行为,let反结构化绑定有点类似于c++的std::move()?于是做了点实验。

#[derive(Debug)]
struct A{
    x:i32,
    y:i32
}
impl A{
    fn new()->A {
        return A{x:123,y:345};
    }
}
#[allow(unused_variables)]
fn main(){
    let a = A::new();
    let A{x:pointx,y:pointy} = a;
    let A{x:pointx,y:pointy} = a;
}

很遗憾,对a执行两次反结构化绑定并没有出现内容被移动。考虑到之前Pair里面不是primitive type ,那只能试着引入非primitive type

#[derive(Debug)]
struct A{
    x:i32,
    y:i32
}
struct B{
    val:A
}

impl A{
    fn new()->A {
        return A{x:123,y:345};
    }
}
#[allow(unused_variables)]
fn main(){
    let a = A::new();
    let A{x:pointx,y:pointy} = a;
    let A{x:pointx,y:pointy} = a;

    let b = B{val:a};
    let B{val:res}=b;
    let B{val:res}=b;
}

这次就如之前一样,对b两次反绑定得到错误,提示b.val已经被移动了。

error[E0382]: use of moved value: `b.val`

原因

然后试着rustc --explain E0382得到了一个很长的解释:

该错误是因为尝试使用一个变量,但是变量的内容已经被移到了其他地方。
比如:

struct MyStruct { s: u32 }

fn main() {
    let mut x = MyStruct{ s: 5u32 };
    let y = x;
    x.s = 6;
    println!("{}", x.s);
}

MyStruct是一个没有被标记为Copy的类型,当我们let y = x时,x的数据被移了出去。

这也是Rust所有权系统的基础:一旦出了工作区,变量的值不能被两个及以上的变量拥有。

有时候我们不需要移动这个值,那么可以使用引用想另一个函数borrow(借)这个值,同时又不改变它的所有权。比如像下面这样,不需要把值移动到calculate_length函数里面,就可以给参数加上引用:

fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

(tips:rust函数声明顺序可以随意)


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
[Matlab] 画图命令发布时间:2022-07-18
下一篇:
MATLAB的PLOT函数线型设置及横坐标为字符串的代码实例发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap