我想清楚地理解如何解释下面这行Rust代码:
Box<dyn std::any::Any + Send + Sync + 'static>
字符串这里有多个关键字:
Any
Send
Sync
'static
其中三个是特质,一个是一生,最后我们有关键字dyn。当这些东西组合在一起的时候,应该如何解释呢?
dyn
nkkqxpd91#
Box<dyn std::any::Any + Send + Sync + 'static>可以解释为堆分配类型,可以是任何类型(Any),可以在线程之间安全地转移所有权(Send),可以在线程之间安全地共享引用(Sync),并且可以在程序的整个持续时间内生存('static)。这意味着你可以在这个Box中存储任何线程安全的数据,并且可以从任何线程访问它。
Box
o4tp2gmn2#
让我们把它分解。
Box<T>
字符串是一个Box类型,它接受一个模板参数(也称为泛型)T。在这种情况下
T
T = dyn Any + Send + Sync + 'static
型'static是一个生命。它告诉我们T是受约束的,如果它是一个引用,那么它必须有静态生命周期,或者如果它不是一个引用,那么它包含的任何引用都必须有静态生命周期。
dyn Any + Send + Sync
我们还剩下:dyn Any + Send + Sync个
是dyn Any + Send + Sync,还是dyn (Any + Send + Sync)?dyn将T标记为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:
dyn Any
dyn (Any + Send + Sync)
&dyn T
vtable
Box<dyn T>
&dyn
Any + Send + Sync
trait X : Any + Send + Sync { }
型结果为Box::<dyn X + 'static>。dyn、X和'static这三个关键字是独立的,它们约束T类型。重要的是要认识到这里有几个概念在起作用:
Box::<dyn X + 'static>
X
trait只是限制胖指针可以指向什么类型的东西。它可以例如强制定义某些功能并且遵守或实现某些行为。
2条答案
按热度按时间nkkqxpd91#
Box<dyn std::any::Any + Send + Sync + 'static>
可以解释为堆分配类型,可以是任何类型(Any
),可以在线程之间安全地转移所有权(Send
),可以在线程之间安全地共享引用(Sync
),并且可以在程序的整个持续时间内生存('static
)。这意味着你可以在这个
Box
中存储任何线程安全的数据,并且可以从任何线程访问它。o4tp2gmn2#
让我们把它分解。
字符串
是一个
Box
类型,它接受一个模板参数(也称为泛型)T
。在这种情况下型
'static
是一个生命。它告诉我们T
是受约束的,如果它是一个引用,那么它必须有静态生命周期,或者如果它不是一个引用,那么它包含的任何引用都必须有静态生命周期。'static
可以独立于dyn Any + Send + Sync
来考虑。我们可以考虑其中一个概念,然后分别考虑其他概念。我们还剩下:
dyn Any + Send + Sync
个是
dyn Any
+Send
+Sync
,还是dyn (Any + Send + Sync)
?dyn
将T
标记为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
* 意味着TYPET
是一个胖指针 *,并且trait实际上可以聚合在一起以产生一些新的trait。例如,我们可以用一些新的东西替换
Any + Send + Sync
:型
结果为
Box::<dyn X + 'static>
。dyn
、X
和'static
这三个关键字是独立的,它们约束T
类型。重要的是要认识到这里有几个概念在起作用:
&dyn T
,这意味着引用的数据类型T
以及通过vtable关联的函数(行为))trait只是限制胖指针可以指向什么类型的东西。它可以例如强制定义某些功能并且遵守或实现某些行为。