我试图初始化一个固定大小的数组,它是一个不可复制的、可以为空的类型,比如Option<Box<Thing>>
,我想把其中的两个数组打包成一个结构体,而不需要额外的间接寻址,我想写这样的代码:
let array: [Option<Box<Thing>>; SIZE] = [None; SIZE];
但它不起作用,因为[e; n]
语法要求e
实现Copy
。当然,我可以将其扩展为SIZE
None
s,但当SIZE
很大时,这可能会很笨拙。我不相信如果不对SIZE
进行非自然编码,就可以使用宏来完成这一操作。有好的方法吗?
是的,使用unsafe
很容易;有没有办法不用unsafe
?
8条答案
按热度按时间prdp8dxp1#
另一种方法使用
arrayvec
crate,它可以很容易地推广到除使用固定值初始化所有内容之外的情况:(playground)
jljoyd4f2#
playground
ipakzgxi3#
在每夜运行的Rust中,你可以使用inline const,这是@user4815162342的一个变体,但它不需要你声明一个单独的常量并重复该类型:
在稳定之前(希望很快),您还可以使用
inline-const
crate,但这确实需要您重复输入。xfb7svmp4#
从Rust 1.38(2019年9月发布)开始,使用中间的
const
初始化器可以得到一个比之前发布的答案更简洁的替代方案,这种方法适用于任何大小的数组:(It可与
Box
配合使用或不配合使用;本示例使用Box
,因为问题中使用了它。)一个限制是数组项必须有一个可以在编译时求值的默认表示-常量、枚举变量或由这些组成的原语容器。
None
或数字元组可以工作,但非空的Vec
或String
不行。gzjq41n45#
您可以使用
Default
trait将数组初始化为默认值:有关工作示例,请参见this playground。
请注意,这只适用于最多包含32个元素的数组,因为
Default::default
只适用于最多[T; 32]
https://doc.rust-lang.org/std/default/trait.Default.html#impl-Default-for-%5BT%3B%2032%5D。sirbozc56#
从Rust1.55.0(引入了
[T]::map()
)开始,以下代码将起作用:Rust Playground
u2nhd7ah7#
我正在复制the answer by chris-morgan并对其进行修改,以便更好地匹配问题,遵循dbaupp downthread的建议,并匹配最近的语法更改:
注意这里需要使用
unsafe
:问题是,如果构造函数panic!
s,这将导致未定义的行为。5hcedyr08#
穿过堆
如果可以创建类型为
Vec
的对象,则可以将其转换为数组:在很多情况下,你实际上想把它保留为
Vec<T>
、Box<[T]>
或Box<[T; N]>
,因为这些类型都把数据放在堆中,大型数组往往很大,你不想把所有的数据都放在堆栈上。另见:
Box
?保持简单
键入所有值:
您可以使用a build script为您生成此代码。有关此代码的示例,请参见: