2015-03-13 10 views
7

का नियम मैं एक कक्षा लिख ​​रहा हूं जो एक सी इंटरफेस का उपयोग करके बनाई गई दो वस्तुओं का उपयोग करता है। ऑब्जेक्ट्स इस तरह दिखते हैं:unique_ptr, कस्टम डिलीटर, और शून्य

typedef struct... foo_t; 
foo_t* create_foo(int, double, whatever); 
void delete_foo(foo_t*); 

(इसी तरह bar_t के लिए)। क्योंकि सी ++ 11, मैं इन्हें एक स्मार्ट पॉइंटर में लपेटना चाहता हूं इसलिए मुझे किसी विशेष विधि को लिखना नहीं है। वर्ग दो वस्तुओं की अनूठी स्वामित्व होगा, इसलिए unique_ptr तार्किक मतलब ... लेकिन मैं अभी भी एक निर्माता लिखने के लिए होगा: shared_ptr साथ,

template <typename T> 
using unique_ptr_deleter = std::unique_ptr<T, void(*)(T*)>; 

struct MyClass { 
    unique_ptr_deleter<foo_t> foo_; 
    unique_ptr_deleter<bar_t> bar_; 

    MyClass() 
     : foo_{nullptr, delete_foo} 
     , bar_{nullptr, delete_bar} 
    { } 

    ~MyClass() = default; 

    void create(int x, double y, whatever z) { 
     foo_.reset(create_foo(x, y, z)); 
     bar_.reset(create_bar(x, y, z)); 
}; 

दूसरा पहलू पर, मैं नहीं करनी होगी एक कन्स्ट्रक्टर लिखें, या एक प्रकार के उपनाम का उपयोग करें, क्योंकि मैं delete_foo में reset() में पास कर सकता था - हालांकि इससे मेरा MyClass कॉपी करने योग्य और मुझे यह नहीं चाहिए।

MyClassunique_ptr अर्थशास्त्र का उपयोग करके लिखने का सही तरीका क्या है और अभी भी शून्य के नियम का पालन करता है?

उत्तर

8

आपकी कक्षा को विनाशक घोषित करने की आवश्यकता नहीं है (यह सही डिफ़ॉल्ट कार्यान्वयन प्राप्त करेगा या नहीं, आप इसे डिफ़ॉल्ट घोषित करते हैं), फिर भी "शून्य का नियम" का पालन करता है।

हालांकि, अगर आप deleters समारोह वस्तुओं बनाकर इस सुधार हो सकता है, बल्कि संकेत से:

template <typename T> struct deleter; 
template <> struct deleter<foo_t> { 
    void operator()(foo_t * foo){delete_foo(foo);} 
}; 
template <> struct deleter<bar_t> { 
    void operator()(bar_t * bar){delete_bar(bar);} 
}; 

template <typename T> 
using unique_ptr_deleter = std::unique_ptr<T, deleter<T>>; 

यह कुछ लाभ हैं:

  • unique_ptr एक अतिरिक्त स्टोर करने के लिए की जरूरत नहीं है सूचक
  • हटाए गए फ़ंक्शन को पॉइंटर
  • के माध्यम से सीधे कन्स्ट्रक्टर लिखने की आवश्यकता नहीं है; डिफ़ॉल्ट कन्स्ट्रक्टर सही काम करेगा।
+0

ऐसा लगता है कि मानक पुस्तकालय में होना चाहिए। – rubenvb

+1

यह बहुत अच्छा था। मैं 'टेम्पलेट <टाइपनाम टी, शून्य (* डिलीटर) (टी *)> स्ट्रक्चर unique_ptr_deleter;' जिसमें एक निजी वर्ग 'डिलीटर' है और फिर 'टाइप = std :: unique_ptr का उपयोग कर' के साथ थोड़ा सा बदलाव कर रहा है ; '। आवश्यक टाइपिंग की मात्रा बचाता है ... तो मैं दोनों एक साथ रह सकता हूं ('unique_ptr_deleter_t foo_;') – Barry

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