2015-05-12 18 views
7

मैं निम्नलिखित इनपुट कमांड के साथ Coliru में इस विषय का पता लगाया:std :: shared_ptr <T> = std :: unique_ptr <T[]> संकलन क्यों करता है, जबकि std :: shared_ptr <T[]> = std :: unique_ptr <T[]> नहीं है?

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out 

परीक्षण here पाया जा सकता है, लेकिन मैं नीचे दिए गए कोड को तैनात किया है। मैंने अपने उदाहरण में int का उपयोग किया, क्योंकि यह एक मूल प्रकार है।


#include <iostream> 
#include <memory> 

struct Foo{ 
    Foo() : 
    a_{0}, b_{1}, c_{-1}, combination_{0.5} {} 

    int 
     a_, 
     b_, 
     c_; 
    double 
     combination_; 
}; 

int main() 
{ 
    //int 
    // *unManagedArray = new int[16]; 
    std::unique_ptr<int[]> 
     uniqueArrayOrigin = std::make_unique<int[]>(16); 
    std::shared_ptr<int> 
      // works but needs call to new 
    // sharedSingleTest{unManagedArray, std::default_delete<int[]>{}}; 
      // works, does not require call to new 
     sharedSingleUnique = std::make_unique<int[]>(16);  
      // compilation error (conversion to non-scalar type) 
    // sharedSingleDerived = uniqueArrayOrigin;     

    // std::shared_ptr<int[]> 
       // compilation errors 
    //  sharedArrayTest{unManagedArray, std::default_delete<int[]>{}}; 
       // compilation error (conversion to non-scalar type) 
    //  sharedArrayUnique = std::make_unique<int[]>(16); 
       // compilation error (conversion to non-scalar type) 
    //  sharedArrayDerived = uniqueArrayOrigin; 

    std::shared_ptr<Foo> 
      // works: specified overload of operator= for shared_ptr 
     nonArrayTest = std::make_unique<Foo>(); 

    std::cout << "done!\n"; 
} 

मैं इतना जवाब के लिए, लेकिन केवल ऊपर referencesstd::shared_ptr एक विशेषज्ञता नहीं होने के कार्यान्वयन में बदल गया पर चारों ओर देखा है, और कहा कि यह काफी हद तक था क्योंकि कोई भी एक उचित देने के लिए परेशान विषय पर मानकों समिति के प्रस्ताव।

मैं उत्सुक,, सब के बाद कर रहा हूँ क्योंकि मैं operator=, std::shared_ptr<T[]>.operator=(std::unique_ptr<T[], Deleter>&&) cppreference पर के 4 अधिभार व्याख्या इंगित करने के लिए इस तरह के वाक्य रचना है कि legal-- T[] और T[]std::shared_ptr के लिए सरणी प्रकार के लिए विशेषज्ञता के राज्य की परवाह किए बिना एक ही प्रकार के हैं जाएगा ।

इसके अलावा, यह वाक्यविन्यास केवल std::make_unique<T[]> के उत्पाद पर काम करता प्रतीत होता है, और एक अद्वितीय सूचक वस्तु नहीं है, जो विषय की मेरी समझ के खिलाफ जाता है - कॉल को प्रभावी रूप से समान नहीं होना चाहिए, हालांकि कोई मौजूदा रूप से चलता है ऑब्जेक्ट, और दूसरा, ठीक है, एक ऑब्जेक्ट चलाता है जिसे अभी बनाया गया है? मैं उम्मीद करता हूं कि पहले मामले में फ़ंक्शन कॉल के बाद उनके बीच एकमात्र अंतर अमान्य std::unique_ptr<T[]> होगा।

एक तरफ ध्यान दें के रूप में, मुझे लगता है कि के बाद से वहाँ एक shared_ptr में एक गतिशील रूप से आवंटित सरणी कि new के उपयोग की आवश्यकता नहीं है के निर्माण का एक तरीका है, मैं इसे मेसियर और अपवाद-असुरक्षित कॉल करने के लिए new T[N] करना पसंद करते हैं चाहिए ?

tl; डॉ:

  1. operator= बिल्कुल std::shared_ptr<T[]> और std::unique_ptr<T[]> के बीच काम नहीं करता है, हालांकि मैं यह काम करने की उम्मीद होगी। क्यूं कर?
  2. यदि कुछ भी है, तो मैं अद्वितीय और साझा पॉइंटर्स के बीच संकलन त्रुटियों का स्रोत होने के लिए T[] से T पर प्रकार रूपांतरण की अपेक्षा करता हूं। यह क्यों काम करता है?
  3. operator=std::shared_ptr<T> और std::make_unique<T[]> के बीच काम करता है लेकिन std::unique_ptr<T[]> नहीं। क्यूं कर?
  4. क्या मैं उन मामलों में मानने के लिए सही हूं जिनके लिए गतिशील रूप से आवंटित, साझा सरणी की आवश्यकता होती है, लेकिन जहां मैं बूस्ट या वेक्टर (नीचे कारणों) का उपयोग नहीं करना चाहता हूं, मुझे operator= std::make_unique<T[]>(N) पर कॉल करना चाहिए?

मैं क्यों उपयोग नहीं कर रहा हूं?

  • बूस्ट: मेरी कंपनी में अभी तक उपयोग की अनुमति नहीं है, और मैं नहीं जानता कि जब या अगर मैं इसे उपयोग करने की स्वीकृति मिल जाएगा।
  • Arrays: मुझे रनटाइम पर इस सरणी का आकार निर्धारित करना होगा।
  • वेक्टर: मैं रीयल-टाइम सिग्नल प्रोसेसिंग सिस्टम पर काम कर रहा हूं, और अतिरिक्त पॉइंटर अव्यवस्था से बचना पसंद करूंगा। मैं अपने हेडर फाइलों में बाहरी पुस्तकालयों से बचने का भी प्रयास कर रहा था (यह उपप्रणाली को पढ़ने और लिखने के बीच संचार के लिए था) हालांकि, अगर मैं महत्वपूर्ण (समयपूर्व अनुकूलन ...) और बुलेट काटने का अंततः इसे बाद में अनुकूलित करना चुना। सवाल अभी भी बनी हुई है।
+4

वर्तमान में, 'std :: shared_ptr' सरणी का समर्थन नहीं करता है। –

+0

स्पष्टीकरण के लिए: यह केवल इतना मामला नहीं है कि सरणी प्रकारों के लिए विशेषज्ञता मौजूद नहीं है, लेकिन 'std :: shared_ptr' सक्रिय रूप से सरणी का समर्थन नहीं करता है? मैंने माना था कि एक विशेषज्ञता की कमी का मतलब है कि यह सरणी प्रकारों पर काम करता था जैसे कि वे किसी अन्य प्रकार के थे। – jaggedSpire

उत्तर

5

§20.8.2.2.1/28:

template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r); 

टिप्पणी: यह निर्माता अधिभार संकल्प में भाग नहीं करेगा जब तक कि unique_ptr<Y, D>::pointerT* के लिए परिवर्तनीय है।

हालांकि, unique_ptr<U[]>::pointer वास्तव में U*, जबकि shared_ptr<U[]> के T*U(*)[] है; और U* को U(*)[] में परिवर्तित नहीं किया जा सकता है, इसलिए अधिभार को कभी नहीं माना जाता है।

+0

@Yakk इसलिए क्योंकि 'टी []' प्रकार के एक विशेषीकृत 'shared_ptr' का व्यवहार वह नहीं है जो मैं उम्मीद कर सकता हूं, बस उन्हें केवल टी.सी. के रूप में समर्थित नहीं माना जा सकता है। कार्यक्षमता के लिए कुछ अच्छे जोड़ों की कमी के बजाय, कहा? – jaggedSpire

+1

@jaggedSpire सटीक रूप से। यह भी मान लें कि 'shared_ptr' कभी भी' हटाएं [] 'को कॉल नहीं करता है। – Columbo

+0

सही ढंग से विशिष्ट 'unique_ptr ' ऑब्जेक्ट से हटाने वाले के साथ आपूर्ति किए जाने पर उचित डिलीटर क्यों नहीं कॉल किया जाएगा? इसके अलावा, मैं आगे पूछताछ सकता है कि क्यों से 'shared_ptr ' प्रश्न में निर्माण में एक कार्यात्मक अंतर नहीं है एक मौजूदा ' unique_ptr' और 'की make_unique ' उत्पाद से? – jaggedSpire

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