2017-07-17 12 views
9

जब लक्षण के साथ कोड लिखने आप एक विशेषता बाध्य में विशेषता रख सकते हैं:<T: Trait> बॉक्स <T> और ट्रैट/बॉक्स <Trait> के बीच क्या अंतर है?

use std::fmt::Debug; 

fn myfunction1<T: Debug>(v: Box<T>) { 
    println!("{:?}", v); 
} 

fn myfunction2<T: Debug>(v: &T) { 
    println!("{:?}", v); 
} 

fn main() { 
    myfunction1(Box::new(5)); 
    myfunction2(&5); 
} 

या सीधे एक Box या संदर्भ प्रकार में:

use std::fmt::Debug; 

fn myfunction3(v: Box<Debug>) { 
    println!("{:?}", v); 
} 

fn myfunction4(v: &Debug) { 
    println!("{:?}", v); 
} 

fn main() { 
    myfunction3(Box::new(5)); 
    myfunction4(&5); 
} 

ये वही उत्पादन दे। तो अंतर क्या है?

(यह सवाल another question से प्रेरित था जहां यह सिर्फ कई मिश्रित अवधारणाओं में से एक था)

उत्तर

9

<T: Trait> Box<T> आप एक विशेषता बाध्य उपयोग कर रहे हैं संकलक है कि आप कुछ प्रकार T का एक उदाहरण के साथ एक Box चाहते बताने के लिए के साथ जो Trait लागू करता है, और आप इसका उपयोग करते समय T निर्दिष्ट करेंगे। जंग कोडर आपके कोड (मोनोमोर्फिज़ेशन) में प्रत्येक अलग T के लिए अलग, कुशल, कोड बना सकता है।

Box<Trait> के साथ आप संकलक है कि आप एक विशेषता वस्तु, एक अज्ञात प्रकार है जो Trait लागू करता है, जिसका अर्थ है कि संकलक गतिशील प्रेषण का उपयोग करेगा करने के लिए एक सूचक के साथ एक Box चाहते कह रहे हैं।

<T: Trait> Box<T>, यानी विशेषता बाध्य: आगे के लिए

use std::fmt::Debug; 

struct Wrapper { 
    contents: Option<Box<Debug>>, 
} 

impl Wrapper { 
    fn new() -> Wrapper { 
     Wrapper { contents: None } 
    } 

    fn insert(&mut self, val: Box<Debug>) { 
    } 
} 

fn main() { 
    let mut w = Wrapper::new(); 
    w.insert(Box::new(5)); 
    w.insert(Box::new("hello")); 
} 

:

use std::fmt::Debug; 

struct Wrapper<T> { 
    contents: Option<Box<T>>, 
} 

impl<T: Debug> Wrapper<T> { 
    fn new() -> Wrapper<T> { 
     Wrapper { contents: None } 
    } 

    fn insert(&mut self, val: Box<T>) { 
    } 
} 

fn main() { 
    let mut w = Wrapper::new(); 

    // makes T for w be an integer type, e.g. Box<i64> 
    w.insert(Box::new(5)); 

    // type error, &str is not an integer type 
    // w.insert(Box::new("hello")); 
} 

Box<Trait>, यानी विशेषता वस्तु

मैं दो उदाहरण जो अंतर थोड़ा स्पष्ट करता है को शामिल किया है विशेषता सीमाओं और विशेषता वस्तुओं के बीच अंतर पर विवरण मैं the section on trait objects in the first edition of the Rust book की अनुशंसा करता हूं।

2

महत्वपूर्ण रूप से, आप नहीं एक संदर्भ (जैसे & या Box) के पीछे सामान्य प्रकार डाल करने के लिए करते हैं है, तो आप सीधे स्वीकार कर सकते हैं:

fn myfunction3<T: Debug>(v: T) { 
    println!("{:?}", v); 
} 

fn main() { 
    myfunction3(5); 
} 

यह बिना monomorphization का एक ही लाभ है अतिरिक्त मेमोरी आवंटन (Box) के नकारात्मक पक्ष या कहीं भी मूल्य के स्वामित्व को रखने की आवश्यकता है (&)।

मैं कहूंगा कि जेनरिक अक्सर डिफ़ॉल्ट विकल्प होना चाहिए - गतिशील प्रेषण/विषमता होने पर आपको केवल विशेषता वस्तु की आवश्यकता होती है।

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