[英]Is it possible to associate memory from one struct with another in Rust?
我知道,在Rust中,編譯器不能保證您以聲明它們的順序獲取結構數據,以節省內存(我也相信某些C代碼優化器在做同樣的事情)。 假設現在我有一棵二叉樹,想將其轉換為雙鏈表。 在CI中將聲明兩個結構:
typedef struct tree{
void* left_child;
void* right_child;
void* data;
}tree_t;
對於樹,以及:
typedef struct list{
void* before;
void* after;
void* data;
}list_t;
用於鏈接列表。 如果現在我想將樹轉換為列表,則可以就地執行此操作,只需將樹的內存與列表結構相關聯並更改指針:
tree_t mytree;
/*fill tree*/
list_t *list_p;
list_p = (list_t)&mytree;
/*change pointers accordingly*/
但是如何在Rust中做這樣的事情? 如果不使用unsafe
代碼,是否有可能? 直到現在我有了我的樹:
struct TreeNode<'a, T> {
left_child: BinaryTreeLink<'a, T>,
right_child: BinaryTreeLink<'a, T>,
data : &'a T,
}
type BinaryTreeLink<'a, T> = Option<Box<TreeNode<'a, T>>>;
列表將是:
struct ListNode<'a, T> {
before: ListLink<'a, T>,
after: ListLink<'a, T>,
data : &'a T,
}
type ListLink<'a, T> = Option<Box<ListNode<'a, T>>>;
但是,現在如何才能有效地將它們轉換為原位?
但是如何在Rust中做這樣的事情? 如果不使用不安全的代碼,是否有可能? 直到現在我有了我的樹
要直接執行相同的操作,您將需要使用不安全的代碼。 函數std::mem::transmute
完全std::mem::transmute
您的需求。 問題是不能保證Rust中的結構布局,因此以下通常是未定義行為:
use std::mem;
let list_link: Option<Box<ListNode<_>>> = unsafe { mem::transmute(tree_node) };
但是,您可以使用C
表示形式,通過強制結構的布局可預測來確保其安全性:
#[repr(C)]
struct TreeNode<'a, T> {
left_child: BinaryTreeLink<'a, T>,
right_child: BinaryTreeLink<'a, T>,
data : &'a T,
}
#[repr(C)]
struct ListNode<'a, T> {
before: ListLink<'a, T>,
after: ListLink<'a, T>,
data : &'a T,
}
您還需要申請#[repr(C)]
的內部類型的定義ListLink
和BinaryTreeLink
。
但是,如何完全避免使用不安全的代碼呢? 如果編寫使用原始數據的轉換函數,則優化器應該能夠將其變為無操作,因為它知道沒有其他代碼可以引用該內存。
<'a, T> impl From<ListNode<'a, T>> for TreeNode<'a, T> {
fn from(other: ListNode<'a, T>) -> ListNode<'a, T>> {
ListNode {
before: other.left_child,
after: other.right_child,
data: other.data,
}
}
}
您絕對應該對此進行基准測試以確保,但是優化器擁有將其變為無操作所需的所有信息,而且很有可能會做到這一點。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.