2016-10-31 12 views
5

मैं Qt5 और QMAKE_CXXFLAGS += -std=c++1y का उपयोग करके एक नई परियोजना शुरू कर रहा हूं। मुझे यकीन नहीं है कि मुझे QScopedPointer या std::unique_ptr पसंद करना चाहिए या नहीं।क्या मुझे QScopedPointer या std :: unique_ptr का उपयोग करना चाहिए?

मैंने somewhere पढ़ा है कि QScopedPointer अब और भी अच्छा नहीं है।

QScopedPointer कोई विशेषताएं unique_ptr कमी है? क्या unique_ptr की कोई विशेषताएं हैं जो मैं QScopedPointer को बदलते समय नहीं चाहूंगा? या ठीक इसके विपरीत?

+3

मैं 'std :: unique_ptr' का उपयोग करूंगा। – NathanOliver

+0

मैं कह सकता हूं कि मैंने क्यूटी स्मार्ट पॉइंटर्स का उपयोग कम कर दिया है और इसके बजाय 'std :: shared_ptr' और' std :: unique_ptr' का उपयोग करने के लिए स्थानांतरित हो गया है। – drescherjm

+2

जब भी मेरे पास मानक लाइब्रेरी और एक अलग से कक्षा के बीच कोई विकल्प होता है, तो मैं हमेशा मानक लाइब्रेरी चुनता हूं जब तक कि कोई अनिवार्य कारण न हो। ऐसा एक अनिवार्य कारण होगा यदि आपको कोड के साथ इंटरऑपरेबिलिटी की आवश्यकता होती है जो दूसरे प्रकार का उपयोग करती है। –

उत्तर

5

QScopedPointerunique_ptr से कड़ाई से कमजोर है क्योंकि यह चाल semantics का समर्थन नहीं करता है।

इसकी कार्यक्षमता अन्यथा बेहद समान है।

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

एकमात्र कारण के बारे में आपको QScopedPointer का उपयोग करना चाहिए मौजूदा कोड अड्डों के साथ अंतःक्रियाशीलता; और यहां तक ​​कि, वे कितने समान हैं, एक एडाप्टर बहुत आसान होगा।

तो यदि आपको अनुकूलित करने की आवश्यकता नहीं है, तो unique_ptr का उपयोग करें।


अब मैं अनुकूलन पर चर्चा करूंगा।

मुश्किल भाग QScopedPointer पर दूसरा पैरामीटर है। यह बहुत ही unique_ptr के दूसरे पैरामीटर से मेल खाता है।

unique_ptr में राज्यव्यापी deleters की अनुमति है। QScopedPointer में वे नहीं हैं।

static void cleanup(T* pointer) 

एक सुंदर वन-टू-वन आधार में

void operator()(T* pointer)const 
unique_ptr में

से मेल खाती है।तो:

template<class QDelete> 
struct std_deleter { 
    template<class T> 
    void operator()(T* target) const { 
    QDelete::cleanup(target); 
    } 
}; 

एक स्टडी डिलीटर के लिए एक क्यूटी डिलीटर को मानचित्र करता है। दूसरी तरह के Deleter राज्यविहीन जा रहा द्वारा सीमित है:

template<class Std_deleter> 
struct Qt_deleter { 
    template<class T> 
    static void cleanup(T* target) { 
    static_assert(std::is_empty<Std_deleter>{}, "Only works with stateless deleters"); 
    Std_deleter{}(target); 
    } 
}; 

अब हम परिवर्तित कर सकते हैं:

template<class T, class D> 
QScopedPointer<T, Qt_deleter<D>> 
to_qt(std::unique_ptr<T, D>&& src) { 
    return src.release(); 
} 
template<class T, class D> 
QScopedPointer<T, Qt_deleter<D>> 
to_qt(std::unique_ptr<T[], D>&& src) { 
    return src.release(); 
} 
template<class T> 
QScopedPointer<T> 
to_qt(std::unique_ptr<T>&& src) { 
    return src.release(); 
} 
template<class T> 
QScopedPointer<T, QScopedPointerArrayDeleter> 
to_qt(std::unique_ptr<T[]>&& src) { 
    return src.release(); 
} 
template< 
    class T, class D, class R=std::unique_ptr<T, std_deleter<D> > 
> 
to_std(QScopedPointer<T, D>&& src) { 
    return R(src.take()); // must be explicit 
} 
template<class T, class R=std::unique_ptr<T>> 
to_std(QScopedPointer<T>&& src) { 
    return R(src.take()); // must be explicit 
} 
template<class T, class R=std::unique_ptr<T[]>> 
to_std(QScopedPointer<T,QScopedPointerArrayDeleter >&& src) { 
    return R(src.take()); // must be explicit 
} 

जो केवल कारण है कि आप QScopedPointer का उपयोग करेंगे शामिल किया गया। कुछ कोने के मामले हैं - डिफ़ॉल्ट डिलीटर QScopedPointer को डिफ़ॉल्ट std::unique_ptr और इसके विपरीत में परिवर्तित किया जाना चाहिए।

सरणी QScopedPointer हटाएं unique_ptr<T[]> और इसके विपरीत में परिवर्तित किया जाना चाहिए।

अन्य मामलों में, मैं बस डिलीटर को लपेटता हूं। सिद्धांत रूप में, वास्तव में फैंसी चाल का ध्यान रखना होगा कि आने वाले डिलीटर को पहले ही लपेट लिया गया था और रैपिंग को उलट दिया गया था, लेकिन यदि आपका कोड ऐसा कर रहा है तो कई दौर-यात्राएं शायद पहले ही कुछ गलत हैं।

+3

"मौजूदा कोड अड्डों के साथ अंतःक्रियाशीलता" मैं इसे "इंटरऑपरेबिलिटी" नहीं कहूंगा। 'QScopedPointer' वास्तव में सी ++ 98 कोड बेस के लिए है (यही कारण है कि 'QScopedPointer' में सैमसंगिक्स नहीं है)। यह देखते हुए कि आप इसे भी स्थानांतरित नहीं कर सकते हैं, यह आमतौर पर केवल एक कार्यान्वयन सहायता है, और आप इसे किसी भी एपीआई में प्रकट नहीं करते हैं ('unique_ptr' के विपरीत)। और क्यूटी परियोजना जानबूझकर 'QScopedPointer' को बेहतर नहीं बना रही है - आपको पहले ही यह मिल गया है, यह' unique_ptr' है। नई, सी ++ 11-सक्षम परियोजनाओं में 'unique_ptr' का उपयोग करें, 'QScopedPointer' नहीं। – peppe

+0

@peppe एक 10 मिलियन लाइन कोड बेस की कल्पना करें जो संदर्भ के माध्यम से QScopedPointer को "रिटर्न" करता है और QScopedPointer Ref और cref के माध्यम से सभी जगहों पर पैरामीटर लेता है, इसमें से कुछ विरासत पुस्तकालयों के पास आपके पास स्रोत नहीं है लेकिन कार्यक्षमता और टेम्पलेट को सुरक्षित रखना चाहिए। मेरा मुद्दा यह है कि, यदि आपके पास मौजूदा कोड बेस का विस्फोट हुआ हेल्स्केप है, तो QScopedPointer का उपयोग न करें। 'To_qt' और' to_std' का उपयोग करें। – Yakk

0

भले ही दोनों वर्गों का मुख्य इरादा समान है, फिर भी उन दोनों के बीच एक महत्वपूर्ण अंतर जो आपको कुछ व्यावसायिक निर्णय लेने में मदद करता है।

QScopedPointer में असाइनमेंट ऑपरेटर नहीं है। जहां std :: unique_ptr असाइनमेंट ऑपरेटर है।

यदि आप अपने क्यूटी ऑब्जेक्ट/कंट्रोल पर सख्त होना चाहते हैं और नहीं चाहते हैं कि असाइनमेंट QScopedPointer का उपयोग करें।

+2

'const unique_ptr' में असाइनमेंट ऑपरेटर भी नहीं है। –

+1

हाँ। लेकिन ओपी ने नहीं कहा था। – Naidu

1

मानक पुस्तकालय से कुछ की तुलना में मानक पुस्तकालय से ऐसा कुछ क्यों नहीं उपयोग करेंगे?

मेरे लिए केवल एक कारण है कि कोई भी अच्छा प्रोग्रामर ऐसा करेगा: यदि बाहरी पुस्तकालय कुछ ऐसा प्रदान करता है जो मानक लाइब्रेरी प्रदान नहीं करता है। क्या यह मामला है?

भविष्य में अपने कार्यक्रम की पोर्टेबिलिटी और अपडेट पर विचार करें, और फिर वह निर्णय लें।

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