2012-08-17 19 views
5

क्या सामग्री बनाने और फू स्वामित्व देने के संबंध में निम्नलिखित एक उचित और कुशल दृष्टिकोण है?पासिंग std :: shared_ptr को रचनाकारों

class Foo 
{ 
    explicit Foo(const std::shared_ptr<Stuff>& myStuff) 
     : m_myStuff(myStuff) 
    { 
    } 

    ... 

private: 
    const std::shared_ptr<Stuff> m_myStuff; 
} 

std::shared_ptr<Stuff> foosStuff(new Stuff()); 
Foo f(foosStuff); 
+0

@sellibitze टाइपो – Baz

+6

वास्तव में नहीं, 'Foo' * स्वामित्व नहीं लेता है। 'Shared_ptr' का बिंदु * साझा * स्वामित्व है। – juanchopanza

+0

या 'std :: shared_ptr foosStuff (नया सामग्री());' – stefaanv

उत्तर

16

मैं दो अंक करना चाहते हैं जब से तुम दक्षता में रुचि रखते हैं:

shared_ptr <> कई मानक पुस्तकालय प्रकार जहां एक चाल निर्माण एक प्रति निर्माण से सस्ता है में से एक है। Shared_ptr का निर्माण करने की प्रतिलिपि धीमी है क्योंकि प्रतिलिपि बनाने के लिए संदर्भ काउंटरों को परमाणु रूप से वृद्धि की आवश्यकता होती है जबकि साझा_प्टर को स्थानांतरित करने के लिए संदर्भित डेटा या काउंटर को स्पर्श करने की आवश्यकता नहीं होती है। डेव अब्राहम द्वारा "Want Speed? Pass by value!" आलेख से कोई यह सीख सकता है कि कुछ स्थितियों में यह मूल्य द्वारा फ़ंक्शन पैरामीटर लेने के लिए वास्तव में फायदेमंद है। यह इन मामलों में से एक है:

class Foo 
{ 
    explicit Foo(std::shared_ptr<Stuff> myStuff) 
    : m_myStuff(move(myStuff)) 
    {} 

    ... 

private: 
    std::shared_ptr<Stuff> m_myStuff; 
}; 

अब आप

Foo f (std::make_shared<Stuff>()); 

जहां तर्क एक अस्थायी है लिख सकते हैं और कोई shared_ptr कभी कॉपी किया जाता है (सिर्फ एक या दो बार ले जाया गया)।

यहां std :: make_shared का उपयोग लाभ है कि केवल एक आवंटन किया जाता है। आपके मामले में आपने स्वयं द्वारा स्टफ ऑब्जेक्ट आवंटित किया था और shared_ptr कन्स्ट्रक्टर को संदर्भ काउंटर आवंटित करना था और साथ ही गतिशील रूप से हटाना था। make_shared यह सिर्फ आपके लिए एक ही आवंटन के साथ करता है।

+1

के लिए मुझे पसंद है कि make_shared समारोह – Baz

+1

Btw: आप एसटीडी :: आप unique_ptr बदलते हैं तो वास्तव में _HAVE_ यह मूल्य द्वारा पारित करने के लिए;) – sellibitze

+0

@sellibitze क्या इसके निर्माता में कक्षा एक shared_ptr पास करने का लाभ है यदि आप इसे रखने के लिए नहीं जा रहे हैं। निश्चित रूप से इस मामले में एक unique_ptr में गुजरना बेहतर होगा और कक्षा से उसमें साझा किया गया है? – jleahy

4

हाँ, यह बिल्कुल उचित है। इस तरह साझा पॉइंटर को प्रबंधित करने में शामिल काम केवल एक बार किया जाना चाहिए, यदि आप इसे मूल्य से पारित करते हैं तो दो बार से अधिक की आवश्यकता होगी। कॉपी कॉपी से बचने के लिए आप make_shared का उपयोग करने पर भी विचार कर सकते हैं। यदि फू एकमात्र मालिक होने के लिए (यानी। आप के आसपास फू बनाने के बाद foosStuff रखने के लिए नहीं जा रहे हैं) तो आप एक एसटीडी उपयोग भी कर सकता है

std::shared_ptr<Stuff> foosStuff(std::make_shared<Stuff>()); 

केवल सुधार आप कर सकते है :: unique_ptr या boost :: scoped_ptr (जो प्री-सी ++ 11 समकक्ष है), जो कम ओवरहेड होगा।

Foo make_foo() { return Foo(std::make_shared<Stuff>()); } 

अब आप auto f = make_foo(); कह सकते हैं:

+0

ठीक है, मुझे अन्य स्मार्ट पॉइंटर्स के बारे में अधिक जानने में देखना चाहिए क्योंकि मैं केवल shared_ptr से वास्तव में परिचित हूं। – Baz

+0

'scoped_ptr' क्या है, यह सी ++ का हिस्सा नहीं है? शायद आप 'std :: unique_ptr' का मतलब है? और क्यों कस्टम हटाना? –

+0

@ क्रिस्टियन राउ: मुझे लगता है कि इसका मतलब क्या है 'boost :: scope_ptr'। डिलीटर बिट पहले (चुपके) संपादन का पुराना संदर्भ हो सकता है? –

3

यह एक make_foo सहायक है करने के लिए और अधिक कुशल हो सकता है। या कम से कम make_shared स्वयं को आमंत्रित करें, क्योंकि shared_ptrnew अभिव्यक्ति से निर्मित एक से अधिक कुशल हो सकता है। और अगर Stuff वास्तव में निर्माता तर्क लेता है, एक निजी सहायक निर्माता उपयुक्त हो सकता है:

struct Foo 
{ 
    template <typename ...Args> 
    static Foo make(Args &&... args) 
    { 
     return Foo(direct_construct(), std::forward<Args>(args)...); 
    }; 

private: 

    struct direct_construct{}; 

    template <typeaname ...Args> 
    Foo(direct_construct, Args &&... args) 
    : m_myStuff(std::make_shared<Stuff>(std::forward<Args>(args)...)) // #1 
    { } 
}; 

आप उपरोक्त make_foo में Foo::make लपेट सकते हैं, या इसे सीधे का उपयोग करें:

auto f = Foo::make(true, 'x', Blue); 

कहा कि, जब तक आप वास्तव में साझा करना स्वामित्व, std::unique_ptr<Stuff> अधिक बेहतर दृष्टिकोण की तरह लगता है: यह अवधारणात्मक रूप से बहुत सरल और कुछ और अधिक कुशल है। उस स्थिति में आप #1 चिह्नित लाइन में m_myStuff(new Stuff(std::forward<Args>(args)...)) कहेंगे।

+0

+1 unique_ptr उल्लेख :) – sellibitze

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