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

Rust使用感受

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

一、关于内存管理

1、rust加入了生命周期和所有权的特性,实现内存自动回收,避免内存泄漏和野指针的问题。

例如:,局部变量离开作用域后Rust会连同变量绑定的内存,不管是否为常量字符串,连同所有者变量一起被销毁释放。所以上面的例子,a销毁后再次访问a就会提示无法找到变量a的错误。

这些所有的一切都是在编译过程中完成的。

2、Rust没有null,取而代之的是None和Option<T>,且Rust并不会像其他语言一样可以为变量默认初始化值,Rust明确规定变量的初始值必须由程序员自己决定。

例如:如果a不初始化,则会产生如下错误:

3、移动语义的概念

Rust的移动语义和C++11标准中的移动语义类似,都是可以解决内存多次释放造成系统崩溃问题。但是Rust的概念稍微有些特殊,来个例子

编译之后会得到如下的错误:

 

编译信息可以看出编译器会做尽可能多的检查,争取在编译发现问题,且编译信息友好,有的问题直接就你提示,告你怎么修改会程序编译。(缺点就是编译时间~~~)

先看红色的编译提示    第三个    错误的意思是在println中访问了被moved的变量a 在Rust中,有个机制叫做“转移move所有权”,意思是,可以把资源的所有权(ownership)从一个绑定a转移(move)成另一个绑定b,被move的变量a不可以继续被使用。

还有一个问题,move后,如果变量a和变量b离开作用域,所对应的内存会不会造成“C++经常遇到的2次释放”的问题?不会的,只有资源的所有者销毁后才释放内存,而无论这个资源是否被多次move,同一时刻只有一个owner(有点类似C++11中的 unique_ptr)所以该资源的内存也只会被释放一次。通过这个机制,就保证了内存安全。

 

我们再看    第一个    的警告提示,在Rust中,如果定义了一个未被使用的变量,是需要给用户提示警告信息,并告诉用户如果想消除此警告信息,例如图中所示,加个”_”即可,但是在实际编程中,未被使用的变量是不会让其存在的。

再看   第二个错误     在Rust中String类型是没有实现Copy特性的,如果将上面的代码中的a改成i32类型,就可以编译通过,因为i32实现了Copy特性,在move时会拷贝资源到新的内存区域,move前后的a和b对应资源内存的地址不同。(Rust中,基本数据类型均实现了Copy特性)

 

二、关于Future

1、什么是Future,可以理解成一种不会立即执行的古怪函数,他会在未来被执行(future名字的由来?)我们可以利用Future,将逻辑异步转成同步的代码,通过and_then将各个future串联起来,将来依次执行,所以,我们在多线程开发过程中,只需要关心future怎么写,怎么传递。缺点是代码可读性不高,通篇都是and_then,脑袋大。

在future的串联过程中,把一个future的返回值传给下一个future的部分有点棘手,在Rust中,我们使用闭包参数来捕获(Rust的闭包有点类似于C++11标准中的lambda表达式)。

 

2、麻烦的Error,把future连接起来并不困难,但是他们的错误类型必须都要匹配上去才行,即链式futures的错误类型必须要统一,否则编译不过!这也是我开发过程中遇到最多的编译错误问题。这就引出了From的概念

单独举个小例子:

假设我们已经定义了两个错误类型ErrorA和ErrorB

fn fut_error_a() -> impl Future<Item = (), Error = ErrorA> {

    err(ErrorA {})

}

fn fut_error_b() -> impl Future<Item = (), Error = ErrorB> {

    err(ErrorB {})

}

然后把他俩串起来

let future = fut_error_a().and_then(|_| fut_error_b());

编译之后出现错误   

    |     let future = fut_error_a().and_then(|_| fut_error_b());

    |                                ^^^^^^^^ expected struct `errors::ErrorB`, found struct `errors::ErrorA`

    |

    = note: expected type `errors::ErrorB`

               found type `errors::ErrorA`

我们在本该有ErrorB的地方得到一个ErrorA,

我们可以利用std::convert::From trait,使用From,可以告诉Rust怎么全自动从元类型转成目标类型

impl From<ErrorB> for ErrorA {

    fn from(e: ErrorB) -> ErrorA {

        ErrorA::default()

    }

}

impl From<ErrorA> for ErrorB {

    fn from(e: ErrorA) -> ErrorB {

        ErrorB::default()

    }

}

 

let future = fut_error_a().map_err(|e| ErrorB::from(e)).and_then(|_| fut_error_b());

这样的话,错误类型一致,编译错误取消。

在开发中,最好单独有个error.rs的文件,专门去做错误类型转换的功能。

三、项目构建

为了解决C/C++项目的管理问题 ,开发出了cmake    、qmake等项目管理工具,但结果并不如人意, C/C++er经常会陷入在掌握语言本身的同时,还要掌握复杂的构建工具语法的窘境。作为rust的代码组织管理工具,cargo提供了一系列的工具,从项目的建立、构建到测试、运行直至部署,为rust  项目的管理提供尽可能完整的手段。

其中说一下最重要的cargo.toml文件。

 

基于git仓库地址,通过URL来描述

基于Rust官方仓库crates.io,通过版本说明来描述

 

[package]: 描述了软件开发者对本项目的各种元数据描述信息,项目名称、版本、作者等等

[dependencies]:描述该项目的各种依赖项

 

四、其它

代码里禁止出现expect(),unwrap()函数。取而代之用默认值,或者修改类型(不用Option,Result)

总之:一句话总结Rust和C++的区别,我的想法就是:

rust:编译时想撞墙。
c++:调试时想跳楼。


鲜花

握手

雷人

路过

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

请发表评论

全部评论

专题导读
上一篇:
Matlab函数返回矩阵发布时间:2022-07-18
下一篇:
Matlab中的eig函数和Opecv中eigen()函数的区别发布时间: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