通用C ++包装器能否实现Rust的所有权模型?


15

浏览有关Rust的并发安全性的这篇文章:

http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html

我想知道在C ++ 11(或更新版本)中可以实现多少这些想法。特别是,我可以创建一个所有者类,将所有权转移到可能传递给它的任何方法吗?似乎C ++有太多传递变量的方法,这是不可能的,但是也许我可以对类或模板施加一些限制,以确保每次方法传递都执行某些模板代码?


从链接的一些话会改善这个问题
马丁巴

2
@delnan(安全)Rust保证您一次对某个事物的引用永远不会超过一个,并且对于一个您也具有只读引用的事物,您永远都不会具有一个可变的引用。它还在线程之间传输数据方面有一些限制。这些共同防止了与线程相关的大量错误,即使在单线程代码中,也使对象状态的推断更加容易。
CodesInChaos

3
您认为您不能以C ++编译器可以验证的方式来表示借用,因此您必须诉诸于运行时强制执行以及相关的性能损失。
CodesInChaos

1
范围所有权不是已经由C ++ 11中的智能指针实现了吗?
Akshat Mahajan

1
@JerryJeremiah Rust具有多种参考类型。基本的&不需要任何类型的升级。如果您试图花点时间来&mut查找同一项目的另一个引用(可变或不可变),则将无法编译。RefCell<T>将检查移至运行时,因此,如果尝试使用.borrow_mut()已处于活动状态.borrow()或的内容,则会感到恐慌.borrow_mut()。Rust还具有Rc<T>(共享的拥有者指针)及其同级对象Weak<T>,但是它们与所有权有关,而不是可变性。贴RefCell<T>在他们里面的可变性。
8bittree '17

Answers:


8

C ++有三种方式将参数传递给函数:按值,由左值参考,并且通过右值参考。其中,按值传递会在被调用函数收到其自己的副本的意义上创建所有权,而按右值引用传递表示值可能已被使用,即调用者将不再使用它。通过左值引用传递意味着该对象是临时从调用方借用的。

但是,这些往往是“按惯例”的,不能始终由编译器检查。并且您可能会意外地将左值引用转换为右值引用std::move()。具体来说,存在三个问题:

  • 引用可以超过其引用的对象。Rust的生命周期系统可以防止这种情况。

  • 任何时候都可以有一个以上的可变/非常量引用活动。Rust的借阅检查器可以防止这种情况。

  • 您不能选择退出参考。如果不知道被调用函数的签名,就无法在调用站点上看到该函数是否创建了对对象的引用。因此,不能通过删除类的任何特殊方法或通过审核呼叫站点是否符合某些“无引用”样式指南来可靠地阻止引用。

生存期问题与基本内存安全性有关。当引用的对象过期时,使用引用当然是非法的。但是,当您将引用存储在对象中时,尤其是当该对象超出当前范围时,很容易忘记生命周期。C ++类型系统无法解决这个问题,因为它根本无法建模对象的生存期。

std::weak_ptr智能指针确实类似于一个普通的参考编码所有权语义,但是需要被引用的对象经由管理shared_ptr,即,是引用计数。这不是零成本的抽象。

虽然C ++具有const系统,但它不会跟踪是否可以修改对象,而是跟踪是否可以通过该特定引用来修改对象。这不能为“无畏并发”提供足够的保证。相反,Rust保证,如果有一个活动的可变引用是唯一的引用(“我是唯一可以更改此对象的人”),并且如果存在不可更改的引用,那么对该对象的所有引用都是不可更改的(“虽然我可以从对象中读取内容,但是没有人可以更改它”)。

在C ++中,您可能很想通过带有互斥量的智能指针来保护对对象的访问。但是如上所述,一旦有了参考,它就可以逃脱其预期的使用寿命。因此,这样的智能指针不能保证它是对其管理对象的单点访问。这样的方案实际上可能在实践中可行,因为大多数程序员都不想破坏自己,但是从类型系统的角度来看,这仍然是完全不合理的。

智能指针的普遍问题是它们是核心语言之上的库。核心语言功能集支持这些智能指针,例如std::unique_ptr需要移动构造函数。但是它们不能解决核心语言中的缺陷。调用函数时隐式创建引用以及将引用悬挂在一起的能力意味着核心C ++语言不健全。无法将可变引用限制为单个引用意味着C ++不能保证在任何类型的并发情况下针对竞争条件的安全性。

当然,在许多方面,C ++和Rust比不相似时更相似,尤其是在它们静态确定的对象生存期的概念上。但是,尽管可以编写正确的C ++程序(只要没有程序员会犯任何错误),Rust可以保证所讨论属性的正确性。


如果问题在于C ++无法跟踪核心语言的所有权,那么是否可以通过元编程来实现该功能?这意味着您将创建一个新的智能指针类,该类将具有内存安全性,方法是(1)强制其仅指向仅使用同一类的智能指针的对象,以及(2)通过模板跟踪所有权
Elliot Gorokhovsky,

2
@ElliotGorokhovsky否,因为模板无法禁用诸如引用之类的核心语言功能。智能指针会使获取引用变得更加困难,但是到那时,您正在与该语言进行斗争–大多数标准库函数都需要引用。也不可能通过模板检查引用的生命周期,因为该语言没有提供生命周期的统一概念。
阿蒙

我明白了,谢谢
Elliot Gorokhovsky
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.