2015-01-08 4 views
6

मुझे एक बड़ी वस्तु चाहिए कि Vec<Vec<MyStruct> किसी फ़ंक्शन द्वारा आरंभ किया जाए। जब मैंक्या मैं कुशलता से जंग में मूल्य से वस्तु वापस कर सकता हूं?

fn initialize() -> Vec<Vec<MyStruct>> { ... } 

C++ में अक्सर ऐसा मैंने सुना है चाहते हैं, वापसी मान अनुकूलन लागू करता है, अगर तुम भाग्यशाली हो और एक अच्छा संकलक है वर्तमान में मैं

fn initialize(mydata : &mut Vec<Vec<MyStruct>>) { ... } 

है। क्या हम यहां प्रतिलिपि अक्षम कर सकते हैं और इसे मूल रूप से फ़ंक्शन में पारित छुपा सूचक द्वारा वापस कर दिया है? और भाषा का आरवीओ हिस्सा या वैकल्पिक अनुकूलन है?

+0

[यह चर्चा] (http://discuss.rust-lang.org/t/implementation-details/948/5) सुझाव देता है कि आरवीओ एक सूचक से बड़ा कुछ भी ट्रिगर करता है। लेकिन एनआरवीओ के संबंध में [यह खुला मुद्दा] (https://github.com/rust-lang/rust/issues/18363) भी है। तो मुझे लगता है कि यह इस बात पर निर्भर करता है कि आप 'प्रारंभिक' को कैसे कार्यान्वित करते हैं। – Michael

उत्तर

12

हाँ, हर तरह से, आप लिखना चाहिए

fn initialize() -> Vec<Vec<MyStruct>> { ... } 

(Btw, Vec नहीं है कि बड़ी है - यह केवल 3 सूचक आकार पूर्णांक है, लेकिन अभी भी)

जंग RVO है, और इस गाइड में विज्ञापित है, उदाहरण के लिए, here। आप इसे स्वयं देख सकते हैं।

#[inline(never)] 
fn initialize() -> Vec<i32> { Vec::new() } 

fn main() { 
    let v = initialize(); 
} 

आप "ASM" बटन के साथ इस कार्यक्रम on playpen चलाते हैं, बाकी सब के बीच में आप यह देख सकता है:

_ZN10initialize20h5d5903a85c1850a8eaaE: 
    .cfi_startproc 
    movq $1, (%rdi) 
    movq $0, 16(%rdi) 
    movq $0, 8(%rdi) 
    movq %rdi, %rax 
    retq 

Vec::new() inlined गया था, लेकिन फिर भी आप विचार देख सकते हैं - के लिए पता ताजा Vec उदाहरण %rdi में फ़ंक्शन में पारित किया गया है, और फ़ंक्शन को इस स्मृति में Vec फ़ील्ड स्टोर करता है, जो स्टैक के माध्यम से अनावश्यक प्रतिलिपि से परहेज करता है। और यह है कि यह कैसे कहा जाता है:

leaq (%rsp), %rdi 
    callq _ZN10initialize20h5d5903a85c1850a8eaaE 

आप देख सकते हैं कि अंततः Vec उदाहरण सीधे ढेर स्मृति में रखा जाएगा।

+0

आईएमओ, एलएलवीएम आईआर आउट पॉइंटर को अधिक स्पष्ट रूप से इंगित करता है। – huon

+0

शायद, लेकिन मुझे एलएलवीएम आईआर कुछ कारणों से असेंबली की तुलना में बहुत कठिन पढ़ता है :( –

+2

इसके लिए हमें केवल हस्ताक्षर की आवश्यकता है: 'आंतरिक फास्टैक शून्य को परिभाषित करें @ प्रारंभ करें (% "struct.collections :: vec :: Vec <[i32]> [# 3] "* नोएलियास nocapture sret dereferenceable (24)) unnamed_addr # 0'। एलएलवीएम आईआर घोषणाओं के लिए समान सी है, ताकि फ़ंक्शन 'शून्य' लौटाता है और एक सूचक (' * ') को' struct.collections :: vec पर ले जाता है :: Vec <[i32]> '। (मैंने इसे स्पष्ट करने के लिए' # [no_mangle] 'का उपयोग किया था।) – huon

संबंधित मुद्दे

 संबंधित मुद्दे