Rust的智能指针std::rc::Rc和std::sync::Arc与C++的智能指针std::shared_ptr和std::atomic_shared_ptr分别类似吗?

3

Rust的智能指针 std::rc::Rcstd::sync::Arc 与C++的智能指针 std::shared_ptrstd::atomic_shared_ptr 之间有类比关系吗?对我来说,它们看起来很相似,但可能存在一些实现细节差异。例如,在C ++中,std::shared_ptr 中,控制块中的引用计数是原子的,尽管指针本身不是。在Rust的 std::rc::Rc 中是否也是如此?


3
似乎atomic_shared_ptr从未成为std的一部分,它 存在于experimental 直到它被 标准化为std::atomic<std::shared_ptr<T>>的特化实现。这有助于回答问题吗?或者您是否希望在考虑到这个事实的情况下重新表述问题? - trent
2个回答

12

Rust的Arc<T>与C++的shared_ptr<T>在很大程度上是等价的

两者都是“智能指针”,通过引用计数提供值的共享所有权。它们都使用原子操作进行内部操作,以便可以安全地在线程之间跟踪所有权。

一个显着的区别是C++的std::shared_ptr实现提供了一个“别名构造函数”,您可以创建一个std::shared_ptr<U>用于std::shared_ptr<T>的嵌套字段,使得std::shared_ptr<U>可以正确跟踪根T对象。

C ++没有Rust的Rc<T>等价物

std::rc::Rcstd::sync::Arc之间唯一的区别是内部引用跟踪不是原子的。这意味着它不能在线程之间使用,但它避免了原子操作的潜在成本。

Rust没有C++的atomic<shared_ptr<T>>等价物

C++的std::atomic是通用的,因此其原子指针类型是一个std::atomic<T*>,而Rust只有专用类型std::sync::atomic::AtomicPtr<T>。C++有一个特化的std::atomic<std::shared_ptr<T>>,以便多个线程可以原子地访问和修改shared_ptr本身,而不仅仅是共享值。 OP提到的std::atomic_shared_ptr没有标准化,而是采用了这种特化。

可能存在等价物的,但我只包括了各自的标准库。

另请参见:


2
当考虑 Rust 是否有atomic<shared_ptr<T>>的“等价”时,值得注意的是,atomic<shared_ptr<T>>在每个平台上都存在,但不保证是无锁的,而AtomicPtr<T>始终是无锁的,但不保证在每个平台上都存在。有一个crate(IRC中的atomic)提供了一个具有类似C++语义的Atomic<T>类型构造器。 - trent
@trentcl 我可能一整天都在叙述诸如"shared_ptr<T>在线程之间是安全的,但这并不意味着T在线程之间是安全的,而 Rust 的类型系统可以确保这一点",或者 C++ 有 这些 函数,而 Rust 有 这些 函数,或者像你所说的标准库选择提供跨平台支持。我尽力给出了差异的总体概述,因为那似乎是问题的重点。 - kmdreko
1
明白了。我的评论并不是对你的答案(或C ++)的批评,更多的是“有趣的事实”而已。 - trent

2
例如在C++的std::shared_ptr中,控制块中的引用计数是原子的,尽管指针本身不是。Rust的std::rc::Rc也是这样吗? 不是的。Arc是shared_ptr的类比:引用计数是原子的(因此是线程安全的),但数据不是(这就是为什么通常会看到Arc>或Arc>,以允许对内部类型进行修改,否则Arc只提供只读访问)。Rc完全未同步,实际上静态地不能在线程之间移动(它是!Send)。C++标准库中没有这样的类型[0]。
尽管 libstdc++ 会在认为没有涉及多线程的情况下使用非线程安全的 shared_ptr,但这更像是一种优化/技巧:https://snf.github.io/2019/02/13/shared-ptr-optimization/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接