2010-07-11 34 views
7

मैं एक class T की std::list की है कहते हैं:std :: सूची <std :: unique_ptr <T>>: गुजर इसके चारों ओर

:

std::list<T> l; 

जब यह कार्यों में गुजर, मैं एक संदर्भ का प्रयोग करेंगे

someFunction(std::list<T> &l) 

unique_ptr एस के std::list के आस-पास (तत्व) को पास करने का सबसे अच्छा तरीका क्या है?

someFunction(std::unique_ptr<T> ptr) 

या इस:

someFunction(T* ptr) 

या इस:

std::list< std::unique_ptr<T> > l; 
इस तरह

someFunction(T &ref) 

और क्या मैं इसे कैसे std::list के back() का उपयोग कर कहेंगे उदाहरण के लिए समारोह? ये आईएमएचओ सभी प्रकार के समकक्ष हैं, लेकिन मुझे यकीन है कि मुझे यहां कुछ याद आ रही है।

धन्यवाद

उत्तर

7

बदतर करने के लिए सबसे अच्छा के लिए आदेश में:

  1. someFunction (स्थिरांक टी &);
  2. कुछ समारोह (टी);
  3. कुछ फ़ंक्शन (कॉन्स std :: unique_ptr < टी > &);
  4. कुछ फ़ंक्शन (std :: unique_ptr < टी > &);

पहला सबसे अच्छा है क्योंकि यह ऑब्जेक्ट को संशोधित नहीं करता है और यह ऑब्जेक्ट के साथ काम करेगा चाहे आप इसे आवंटित कैसे करें (उदाहरण के लिए, आप किसी भी समस्या के साथ shared_ptr पर स्विच कर सकते हैं)।

नंबर दो भी स्मार्ट पॉइंटर का उपयोग करने के बावजूद काम करेगा; हालांकि, यह मानता है कि आप ऑब्जेक्ट को संशोधित कर सकते हैं, और जब भी आप कुछ स्थिर बना सकते हैं, तो आपको चाहिए।

संख्या 3 और 4 दोनों ऑब्जेक्ट को प्रतिबिंबित करने की अनुमति देते हैं; हालांकि, # 3 स्मार्ट पॉइंटर को संशोधित करने की अनुमति नहीं देता है, जबकि संख्या 4 करता है। दोनों को नुकसान होता है कि वे unique_ptr के उपयोग को मजबूर करते हैं, जबकि ऊपर दिए गए दो स्मार्ट पॉइंटर क्लास के बावजूद काम करेंगे।

मूल्य के आधार पर एक अद्वितीय_ptr पास करना, जैसा कि आपके कुछ अन्य उदाहरणों में है, एक विकल्प नहीं है; एक अद्वितीय_पीआरआर अद्वितीय होना चाहिए। यदि आप इसे कॉपी कर रहे हैं, तो साझा_ptr का उपयोग करने पर विचार करें।

पहले दो के लिए, यदि आप) पीठ के परिणाम (पर यह लागू है, यह दिखाई देगा:

someFunction(*(lst.back())); // dereference lst.back() before passing it in. 

बाद के दो के लिए, यदि आप पीठ के resut पर यह लागू(), यह विचार करेंगे की तरह:

someFunction(lst.back()); // pass the smart pointer, not the object to 
          // which the smart pointer currently points. 
+0

में गहराई से स्पष्टीकरण के लिए धन्यवाद। तो स्मार्ट पॉइंटर्स के लिए कोई विशेष अर्थशास्त्र आवश्यक नहीं है (dereferencing को छोड़कर)। मुझे 'कॉन्स' सामान के बारे में पता था, लेकिन इस मामले में मुझे पास होने वाली 'टी' ऑब्जेक्ट को संशोधित करने की आवश्यकता है। – rubenvb

1

नहीं मूल्य द्वारा पारित unique_ptr, सभी यह एक std::move बिना संकलन नहीं होगा की पहली करो और इसे खाली होगा यदि आप उपयोग std::move कर मूल्य जो आपने अपने list में संग्रहीत किया है और आप इसे और अधिक एक्सेस नहीं कर पाएंगे।

इसका कारण यह है unique_ptr copyable नहीं है, यह प्रकार unique_ptr::unique_ptr(const unique_ptr<T>& other) बजाय यह केवल एक कदम निर्माता (unique_ptr::unique_ptr(unique_ptr<T>&& source)) है की एक प्रति निर्माता नहीं है।

0

unique_ptr और भी कक्षाओं/उदाहरणों वाले unique_ptr std :: सूची (और अन्य कंटेनरों) में इस्तेमाल किया जा सकता है, बशर्ते वे चाल निर्माताclass_name(class_name &&) परिभाषित किया गया है कि (जो unique_ptr, ज़ाहिर है, है)।

जब आप उन तत्वों के आसपास पारित, तो आप हमेशा आगे बढ़ रहे हैं (और नहीं कॉपी करने) के लिए उन्हें, ताकि आप हमेशा) lvalues ​​पर std :: चाल (उपयोग करते हैं, की तरह में
my_list.push_back(std::move(my_element));
इस से दिखाई दे रही है कि आप कर रहे हैं सूची में तत्व को गुजरना (= चलाना), और उस ऑपरेशन के बाद my_element "खाली" (खाली खाली_ptr की तरह) है।

उदाहरण:

typedef std::unique_ptr<uint8_t[]> data_ptr; 

class data_holder 
{ 
private: 
    int something_about_data; 
    data_ptr data; 
public: 
    data_holder(data_ptr && _data) 
     : data(std::move(_data)) 
    {} 

    // hey compiler, please generate a default move constructor for me 
    // despite of present destructor 
    data_holder(data_holder &&) = default; 

    ~data_holder() 
    { 
     // ... 
    } 

    bool is_empty() const { return ! bool(data); } 
} 

// ... 
{ 
    // ... 
    data_holder the_element(data_ptr(new uint8_t[DATA_SIZE])); 

    // move the_element into the_list 
    the_list.push_back(std::move(the_element)); 
    if (the_element.is_empty()) 
     std::cerr << "data_holder 'the_element' is now empty!" << std::endl; 
    // ... 
} 
संबंधित मुद्दे