如何在Rust中默认初始化包含数组的结构体?

18

如何声明一个包含数组的结构体,并创建一个零初始化实例是推荐的方式?

这是结构体:

#[derive(Default)]
struct Histogram {
    sum: u32,
    bins: [u32; 256],
}

还有编译器错误:

error[E0277]: the trait bound `[u32; 256]: std::default::Default` is not satisfied
 --> src/lib.rs:4:5
  |
4 |     bins: [u32; 256],
  |     ^^^^^^^^^^^^^^^^ the trait `std::default::Default` is not implemented for `[u32; 256]`
  |
  = help: the following implementations were found:
            <[T; 14] as std::default::Default>
            <&'a [T] as std::default::Default>
            <[T; 22] as std::default::Default>
            <[T; 7] as std::default::Default>
          and 31 others
  = note: required by `std::default::Default::default`

如果我尝试为数组添加缺失的初始化器:

impl Default for [u32; 256] {
    fn default() -> [u32; 255] {
        [0; 256]
    }
}

I get:

error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
 --> src/lib.rs:7:5
  |
7 |     impl Default for [u32; 256] {
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
  |
  = note: the impl does not reference any types defined in this crate
  = note: define and implement a trait or new type instead

我做错了什么吗?

4个回答

15

Rust并未为所有数组实现Default,因为它没有非类型多态性。因此,只为少数大小实现了Default

但是,您可以为您的类型实现默认值:

impl Default for Histogram {
    fn default() -> Histogram {
        Histogram {
            sum: 0,
            bins: [0; 256],
        }
    }
}

注意:我认为为实现Default本来就很可疑;为什么要选择0而不是142?没有好的答案,因此真正的默认值并不明显。


1
我只使用了默认值,因为在标准库中,Zero被标记为已弃用。在没有~Zero trait的情况下,我认为固定大小的数组更可能用于向量加法而不是其他任何操作,并且零向量是加法的恒等向量,是默认选择更自然的选择。但这是我们正在进行的一些严肃的讨论 :) - Andrew Wagner
你好,这会导致很大的成本吗?我是一个新手,认为[0;256]将首先在堆栈/堆的某个位置被创建和初始化,然后移动Histogram.bins中。因此,大数组被移动,其中包括复制和丢弃。谢谢! - ch271828n
@ch271828n:就语言而言,你是对的。但一旦优化器开始处理代码,情况将会发生很大变化。首先,没有必要“Drop”数组,因为它的元素都不需要“Drop”。其次,编译器实际上可能只需初始化Histogram的元素为0,而无需逐个初始化。第三,根据调用者的情况,它可能永远不会实际生成结构体,甚至可能不会生成数组...如果给予机会,优化编译器可以进行惊人的转换。 - Matthieu M.

6

很抱歉,您不能这样做,您需要自己为您的结构实现Default

struct Histogram {
    sum: u32,
    bins: [u32; 256],
}

impl Default for Histogram {
    #[inline]
    fn default() -> Histogram {
        Histogram {
            sum: 0,
            bins: [0; 256],
        }
    }
}

数字类型与此情况无关,更像是固定大小数组的问题。它们仍需要通用数字字面量来本地支持此类事物。

谢谢Vladimir!Matthieu回答得更快,但你的回答有内联。如果可以的话,我都会接受! - Andrew Wagner
是的,我在另一个答案出现的那一刻按下了提交按钮 :) 没关系,一切都是公平的 :) - Vladimir Matveev

4
如果您确定要将每个字段初始化为零,则可以使用以下方法:

如果您确定要将每个字段初始化为零,则可以使用以下方法:

impl Default for Histogram {
    fn default() -> Histogram {
        unsafe { std::mem::zeroed() }
    }
}

1

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