2016-12-14 73 views
2

當我開始學習Rust的時候,我天真地認爲Rust的特性指針像C++指針一樣被實現,並且編寫了一些甚至在這個假設下也能工作的代碼。具體來說,我寫的代碼接口與需要閱讀和尋求流的FFI庫,它是這樣的:特質指針

struct StreamParts { 
    reader: *mut Read, 
    seeker: *mut Seek, 
} 

fn new_ffi_object<T: Read + Seek + 'static>(stream: T) -> FFIObject { 
    let stream_ptr = Box::into_raw(Box::new(stream)); 
    let stream_parts = Box::into_raw(Box::new(StreamParts { 
     reader: stream_ptr as *mut Read, 
     seeker: stream_ptr as *mut Seek, 
    })); 

    ffi_library::new_object(stream_parts, ffi_read, ffi_seek, ffi_close) 
} 

extern "C" fn ffi_read(stream_parts: *mut StreamParts, ...) -> c_ulong { 
    (*stream_parts.reader).read(...) 
    ... 
} 

extern "C" fn ffi_seek(stream_parts: *mut StreamParts, ...) -> c_ulong { 
    (*stream_parts.seeker).seek(...) 
    ... 
} 

extern "C" fn ffi_close(stream_parts: *mut StreamParts) { 
    mem::drop(Box::from_raw(stream_parts.reader)); 
    mem::drop(Box::from_raw(stream_parts)); 
} 

和它的工作。然而,有三件事我不完全理解它爲什麼會起作用:

  1. Rust的特質對象很胖,包含兩個指針。因此,與C++不同,*mut Read是一個指向特徵對象的指針,是否正確?這個特質對象分配在哪裏?鐵鏽文件沒有涉及這個具體案例。
  2. 我正確地認爲mem::drop(Box::from_raw(stream_parts.reader))完全丟棄原始流嗎?
  3. 爲什麼new_ffi_object()需要'static
+0

有趣的問題;我知道Rust引用很胖,但我不知道指針是否(我認爲它們必須是?)。 –

+1

[每個問題有一個問題,請](http://meta.stackexchange.com/q/39223/281829)。想想你在尋找這些問題的答案(**你搜索了,對嗎?**)。你會*點擊任何一個標題爲「指向特質」的問題嗎? SO並不是要回答你的問題,而是要爲將來所有人**建立一個世界級的知識庫。我保證你是否分開提問,其中至少有一個已經得到答覆。 – Shepmaster

回答

4

指針和引用的行爲完全相同,除了借用檢查器禁止引用懸掛引用以及需要將指針取消引用包裝到unsafe塊中的事實。

  1. 所以是的,sizeof::<*mut Read>() == sizeof::<*mut()>() * 2。特質對象沒有被分配到任何地方。它只不過是一個具有兩個字段的結構。一個是指向數據的指針,另一個是指向vtable的指針。這個vtable被分配在靜態存儲器中。
  2. 正確。它訪問reader的vtable指針並在vtable中查找drop impl。
  3. 如果您沒有'static生命週期,您的T可能包含的參考文獻的壽命短於'static。所有這一生的界限說的是T沒有這樣的引用,並且因此可以在沒有限制的情況下被複制,即使在堆上。