2017-07-25 25 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

相关问题