2017-07-25 53 views
0

我正試圖構建一個自定義的類似String結構的小字符串優化實現。現在,工會被允許在穩定的鏽,我想出了下面的代碼:如何在穩定的Rust中分配一個原始的可變指針?

struct Large { 
    capacity: usize, 
    buffer: *mut u8, 
} 

struct Small([u8; 16]); 

union Container { 
    large: Large, 
    small: Small, 
} 

struct MyString { 
    len: usize, 
    container: Container, 
} 

我似乎無法找到一種方法如何分配該*mut u8。是否有可能在穩定的鐵鏽?它看起來像使用alloc::heap會工作,但它只在夜間可用。

+0

FWIW,'String'本身不能使用SSO,因爲它暴露了某些方法。您將無法複製完整的API,但希望這不會阻止您的用例。 – Shepmaster

回答

2

如果你想分配的u8,而不是一個單一的u8集合,你可以創建一個Vec,然後將其轉換成組成片,比如通過調用as_mut_ptr

use std::mem; 

fn main() { 
    let mut foo = vec![0; 1024]; // or Vec::<u8>::with_capacity(1024); 

    let ptr = foo.as_mut_ptr(); 
    let cap = foo.capacity(); 
    let len = foo.len(); 
    mem::forget(foo); // Avoid calling the destructor! 

    let foo_again = unsafe { Vec::from_raw_parts(ptr, len, cap) }; // Rebuild it to drop it 
    // Do *NOT* use `ptr`/`cap`/`len` anymore 
} 

回覆分配雖然有點痛苦;你不得不回到Vec轉換並做整個舞蹈向前和向後

話雖這麼說,你Large結構似乎缺少一個length,這將是從量是不同的。你可以使用Vec而不是寫出來。我現在看到它在層次結構中有點兒了。

我不知道是否有一個完整的String不會是一個容易得多,即使它是在一個有點不太有效長度爲雙數...

union Container { 
    large: String, 
    small: Small, 
} 

參見:

+1

長度字段在'MyString'中,它也包含'Large'或'Small'。 – interjay

+0

@interjay啊,的確如此。 – Shepmaster

+0

這正是我期待的!謝謝!不知何故,我不知道我可以使用Vec進行分配和釋放。 –

1

Box::into_raw()怎麼樣?

struct TypeMatches(*mut u8); 
TypeMatches(Box::into_raw(Box::new(0u8))); 

但是很難從你的代碼段告訴我們,如果這是你真正需要的。您可能需要一個真正的分配器,並且您可以使用libc::mallocas強制轉換,如this example

+0

分配一個'u8'。 OP想要一個以上的緩衝區。 – interjay

+0

@interjay這是真的,但問的問題是如何分配*指針*,這是一個有效的答案。我期望來自搜索引擎的人會發現這個問題和答案有用。 – Shepmaster

2

有一個memalloc crate它提供了一個穩定的分配API。它是由與Vec::with_capacity分配內存,然後提取指針來實現:

let vec = Vec::with_capacity(cap); 
let ptr = buf.as_mut_ptr(); 
mem::forget(vec); 

釋放內存,使用Vec::from_raw_parts

相關問題