如何在Rust中解释由多个trait组成的动态trait对象类型?

3bygqnnd  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(155)

我想清楚地理解如何解释下面这行Rust代码:

Box<dyn std::any::Any + Send + Sync + 'static>

字符串
这里有多个关键字:

  • 第一个月
  • Any
  • Send
  • Sync
  • 'static

其中三个是特质,一个是一生,最后我们有关键字dyn
当这些东西组合在一起的时候,应该如何解释呢?

nkkqxpd9

nkkqxpd91#

Box<dyn std::any::Any + Send + Sync + 'static>可以解释为堆分配类型,可以是任何类型(Any),可以在线程之间安全地转移所有权(Send),可以在线程之间安全地共享引用(Sync),并且可以在程序的整个持续时间内生存('static)。
这意味着你可以在这个Box中存储任何线程安全的数据,并且可以从任何线程访问它。

o4tp2gmn

o4tp2gmn2#

让我们把它分解。

Box<T>

字符串
是一个Box类型,它接受一个模板参数(也称为泛型)T。在这种情况下

T = dyn Any + Send + Sync + 'static


'static是一个生命。它告诉我们T是受约束的,如果它是一个引用,那么它必须有静态生命周期,或者如果它不是一个引用,那么它包含的任何引用都必须有静态生命周期。

  • 在该表达式中,寿命参数可以独立于其余内容来考虑。换句话说,'static可以独立于dyn Any + Send + Sync来考虑。我们可以考虑其中一个概念,然后分别考虑其他概念。

我们还剩下:dyn Any + Send + Sync

  • 这应该如何解释?

dyn Any + Send + Sync,还是dyn (Any + Send + Sync)
dynT标记为trait对象。这意味着&dyn T是一个胖指针,它有一个指向一些数据的指针,还有一个指向一些类似vtable的对象的指针,这些对象包含了我们可能希望与数据结合调用的相关函数的可执行代码。(参见:https://doc.rust-lang.org/reference/types/trait-object.html
Box<dyn T>的行为类似于&dyn T
因此,我们知道&dyn T是一个16字节的内存块,包含两个指针,一个用于数据,一个用于代码,并且与数据相关联的任何类型都必须受到静态生存期的约束,这限制了任何相关引用的生存期。Box<dyn T>本质上是一个封装了这个引用类型的类型。
这表明正确的解释是将dyn独立于后面的任何trait来考虑,因为&dyn * 意味着TYPE T是一个胖指针 *,并且trait实际上可以聚合在一起以产生一些新的trait。
例如,我们可以用一些新的东西替换Any + Send + Sync

trait X : Any + Send + Sync { }


结果为Box::<dyn X + 'static>dynX'static这三个关键字是独立的,它们约束T类型。
重要的是要认识到这里有几个概念在起作用:

  • 类型,也就是内存中的数据布局(这里是一个胖指针&dyn T,这意味着引用的数据类型T以及通过vtable关联的函数(行为))
  • 特质限制
  • 任何关联引用的生存期约束

trait只是限制胖指针可以指向什么类型的东西。它可以例如强制定义某些功能并且遵守或实现某些行为。

相关问题