簡體   English   中英

如何創建包含大型數組的結構數組?

[英]How to create an array of structs containing large arrays?

如何創建包含固定大小的大數組的結構數組? 我想使用數組而不是向量。

此代碼是一個示例,但未編譯

struct _Tmove {
    data1: usize,
    data2: u64,
    data3: bool,
}

struct _TmoveP {
    data4: Box<[_Tmove]>,
    data5: isize,
}

fn main() {
    let mut gen_list = Box::new([
        _TmoveP {
            data5: 1,
            data4: Box::new([_Tmove { data1: 5, data2: 1, data3: true }; 300]),
        }
        ; 100000]);

    assert!(gen_list[0].data4[0].data1==5);
}
error[E0277]: the trait bound `_Tmove: std::marker::Copy` is not satisfied
--> src/main.rs:16:29
       |
    16 |             data4: Box::new([_Tmove { data1: 5, data2: 1, data3: true }; 300]),
                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the `Copy` trait is required because the repeated element will be copied

error[E0277]: the trait bound `_TmoveP: std::marker::Copy` is not     satisfied
--> src/main.rs:13:33
    |
13  |     let mut gen_list = Box::new([
    |                                 ^
    |
    = note: the `Copy` trait is required because the repeated element will be copied

我正在使用Rust 1.12。

為了從初始化語法中受益: [expr; N] [expr; N]expr的結果需要為Copy (因為需要進行復制)。

#[derive(Copy, Clone)]
struct _Tmove {
    data1: usize,
    data2: u64,
    data3: bool,
}

#[derive(Copy, Clone)]
struct _TmoveP {
    data4: Box<[_Tmove]>,
    data5: isize,
}

但是,在這種情況下, _TmoveP 不能Copy因為它包含不是CopyBox

好吧,讓我們擺脫Box

#[derive(Copy, Clone)]
struct _TmoveP {
    data4: [_Tmove; 300],
    data5: isize,
}

聽起來不錯嗎?

但不幸的是, [_Tmove; 300] [_Tmove; 300]也不Clone :(很不幸,我們遇到了Rust編譯器的限制(它的大小小於32)。

Copy非常容易...但是首先我們必須手動實現Clone 天真的方法很有趣,但是很簡單:

impl Clone for _TmoveP {
    fn clone(&self) -> _TmoveP {
        unsafe {
            let mut res = _TmoveP {
                data4: std::mem::uninitialized(),
                data5: self.data5,
            };

            std::ptr::copy_nonoverlapping(
                &self.data4 as *const _Tmove,
                std::mem::transmute(&mut res.data4),
                300
            );

            res
        }
    }
}

注意:由於某些原因&mut res.data4 as *mut _不會編譯...無論:x

但是, @ FrancisGagné在評論中提醒我, Copy類型有一個怪異的竅門:

impl Clone for _TmoveP {
    fn clone(&self) -> _TmoveP { *self }
}

由於某種原因,這種方法行之有效,並且在這些情況下很方便。

最后,這可行...哦,等等, main有一個問題!

fn main() {
    let gen_list = Box::new([
        _TmoveP {
            data5: 1,
            data4: [_Tmove { data1: 5, data2: 1, data3: true }; 300],
        }
        ; 100000]);

    assert!(gen_list[0].data4[0].data1==5);
}

好了, 我們走了


僅對小於32的大小真正起作用的數組有什么處理?

簡而言之:Rust還不支持非類型的泛型參數。

數組在某種程度上是特殊情況,但是需要獨立地為每個大小實現特征...因此標准庫為最大為32的數組實現其特征,因為這似乎是一個不錯的折衷。

之所以收到此錯誤,是因為您嘗試使用默認的初始化語法初始化數組,但是您的結構未實現Copy trait,因此這是不允許的。 您可以在此處看到原因,但簡而言之,默認的初始化語法將創建您的結構的一個副本,然后嘗試將其復制100,000次。 顯然,如果您的結構未標記為Copy ,則不允許這樣做,因此會引發錯誤。

通常,可以通過將兩個結構都標記為Copy來解決此問題,如下所示:

#[derive(Clone, Copy)]
struct _Tmove {
    data1: usize,
    data2: u64,
    data3: bool,
}

#[derive(Clone, Copy)]
struct _TmoveP {
    data4: Box<[_Tmove]>,
    data5: isize,
}

但是,您會注意到它仍然無法編譯,因為您實際上沒有數組。 您實際上已將類型用於切片( 請看一下類似的問題 )。 實現Copy ,使你的代碼不能編譯,因為_TmoveP結構只能得到Copy ,如果所有的字段都Copy

目前尚不清楚數組是否將始終具有固定大小。 如果可以,則需要使用類型[T; N] [T; N] ,其中T是您的類型, N是元素的數量(例如[i32; 300] )。 如果不是,則需要Vec<T>

如果使用數組,則會遇到另一個問題 陣列實現Copy (最多32個),而不是Clone ,我們需要實現Clone_TmoveP之前,我們就可以實現Copy 因此,讓我們自己做:

impl Clone for _TmoveP {
    fn clone(&self) -> _TmoveP {
        _TmoveP {
            data4: self.data4,
            data5: self.data5
        }
    }
}

然后,您可以從_TmoveP刪除#[derive(Clone)] (僅保留Copy ),我們終於找到了一個_TmoveP解決方案! 是我的解決方案的游樂場鏈接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM