सी ++ 11 के साथ, मैं खुद से पूछ रहा था कि अगर C++ 11 में boost :: ptr_containers का प्रतिस्थापन है। मुझे पता है कि मैं उदाहरण का उपयोग कर सकता हूँ एक std::vector<std::unique_ptr<T> >
, लेकिन मुझे यकीन नहीं है कि यह एक पूर्ण प्रतिस्थापन है या नहीं। इन मामलों को संभालने का अनुशंसित तरीका क्या है?std :: unique_ptr के बनाम एसटीएल कंटेनर :: ptr_container
उत्तर
वे वास्तव में दो समान लेकिन विभिन्न समस्याओं को हल करते हैं।
एक सूचक कंटेनर एक कंटेनर में ऑब्जेक्ट्स को स्टोर करने का एक तरीका है जो मानकों की बजाय आवंटित स्मृति के पॉइंटर्स होने के लिए होता है। वे अपनी शक्ति में को छिपाते हैं कि तथ्य यह है कि वे पॉइंटर्स के कंटेनर हैं। इसका अर्थ है:
- कंटेनर में प्रविष्टियां न्यूल नहीं हो सकती हैं।
- मानदंडों और कार्यों से प्राप्त मान संदर्भ प्रकार के लिए हैं, प्रकार के पॉइंटर्स नहीं।
- कई मानक एल्गोरिदम के साथ काम करना मुश्किल हो सकता है ... मुश्किल। और "मुश्किल" से, मेरा मतलब टूटा हुआ है। सूचक कंटेनरों का अपना अंतर्निर्मित एल्गोरिदम होता है।
हालांकि, तथ्य यह है कि सूचक कंटेनर पता है कि वे संकेत के कंटेनरों को कर रहे हैं, वे कुछ नई कार्यक्षमता की पेशकश कर सकते हैं:
- एक
clone
सदस्य समारोह है कि एक गहरी प्रतिलिपि करता है, प्रयोग के माध्यम से ऑब्जेक्ट के प्रकार पर एक निश्चित "क्लोनेबल" अवधारणा का। - कंटेनर की अपनी वस्तुओं के स्वामित्व को जारी करने की क्षमता (उदाहरण के लिए एक उथली प्रतिलिपि के बाद)।
- अन्य कंटेनरों में स्वामित्व स्थानांतरित करने के लिए अंतर्निहित फ़ंक्शंस।
वे वास्तव में काफी अलग अवधारणाएं हैं। ऐसी कई चीजें हैं जिन्हें आपको मैन्युअल रूप से करना होगा कि पॉइंटर कंटेनर स्वचालित कार्यों के साथ स्वचालित रूप से कर सकते हैं।
यदि आपको वास्तव में पॉइंटर्स के कंटेनर की आवश्यकता है, तो आप unique_ptr
के कंटेनर का उपयोग कर सकते हैं। लेकिन अगर आपको ऑब्जेक्ट्स का एक गुच्छा स्टोर करने की ज़रूरत है जो आप आवंटित करने के लिए होते हैं, और आप स्वामित्व और ऐसे लोगों के साथ विशेष खेल खेलना चाहते हैं, तो पॉइंटर कंटेनर एक बुरा विचार नहीं है।
मुझे लगता है कि आप कह सकते हैं कि उनमें से एक स्पष्ट रूप से पॉइंटर्स का कंटेनर है जबकि दूसरा पॉलिमॉर्फिक ऑब्जेक्ट्स के लिए एक कंटेनर है ... – Mehrdad
मैंने एक छोटा प्रोग्राम लिखने का फैसला किया जो कुछ पॉलिमॉर्फिक ऑब्जेक्ट्स को एक कंटेनर में रखता है (पॉइंटर से ढेर तक), और फिर उस कंटेनर को std :: एल्गोरिदम के साथ उपयोग करें। मैंने उदाहरण के तौर पर std::remove_if
चुना है।
यहाँ कैसे मैं vector<unique_ptr<T>>
साथ यह करना होगा:
#include <vector>
#include <memory>
#include <iostream>
class Animal
{
public:
Animal() = default;
Animal(const Animal&) = delete;
Animal& operator=(const Animal&) = delete;
virtual ~Animal() = default;
virtual void speak() const = 0;
};
class Cat
: public Animal
{
public:
virtual void speak() const {std::cout << "Meow\n";}
virtual ~Cat() {std::cout << "destruct Cat\n";}
};
class Dog
: public Animal
{
public:
virtual void speak() const {std::cout << "Bark\n";}
virtual ~Dog() {std::cout << "destruct Dog\n";}
};
class Sheep
: public Animal
{
public:
virtual void speak() const {std::cout << "Baa\n";}
virtual ~Sheep() {std::cout << "destruct Sheep\n";}
};
int main()
{
typedef std::unique_ptr<Animal> Ptr;
std::vector<Ptr> v;
v.push_back(Ptr(new Cat));
v.push_back(Ptr(new Sheep));
v.push_back(Ptr(new Dog));
v.push_back(Ptr(new Sheep));
v.push_back(Ptr(new Cat));
v.push_back(Ptr(new Dog));
for (auto const& p : v)
p->speak();
std::cout << "Remove all sheep\n";
v.erase(
std::remove_if(v.begin(), v.end(),
[](Ptr& p)
{return dynamic_cast<Sheep*>(p.get());}),
v.end());
for (auto const& p : v)
p->speak();
}
यह आउटपुट:
Meow
Baa
Bark
Baa
Meow
Bark
Remove all sheep
destruct Sheep
destruct Sheep
Meow
Bark
Meow
Bark
destruct Dog
destruct Cat
destruct Dog
destruct Cat
जो मेरे लिए अच्छा लग रहा है।
boost::ptr_vector<Animal> v;
v.push_back(new Cat);
v.push_back(new Sheep);
v.push_back(new Dog);
v.push_back(new Sheep);
v.push_back(new Cat);
v.push_back(new Dog);
for (auto const& p : v)
p.speak();
std::cout << "Remove all sheep\n";
v.erase(
std::remove_if(v.begin(), v.end(),
[](Animal& p)
{return dynamic_cast<Sheep*>(&p);}),
v.end());
for (auto const& p : v)
p.speak();
algorithm:1897:26: error: overload resolution selected deleted operator '='
*__first = _VSTD::move(*__i);
~~~~~~~~^~~~~~~~~~~~~~~~~~
test.cpp:75:9: note: in instantiation of function template specialization 'std::__1::remove_if<boost::void_ptr_iterator<std::__1::__wrap_iter<void
**>, Animal>, Sheep *(^)(Animal &)>' requested here
std::remove_if(v.begin(), v.end(),
^
test.cpp:12:13: note: candidate function has been explicitly deleted
Animal& operator=(const Animal&) = delete;
^
1 error generated.
समस्या boost::ptr_vector
की एक विशेषता है:: हालांकि मैं ptr_vector
समस्याग्रस्त को यह अनुवाद पाया iterators आंतरिक रूप से संग्रहीत संकेत नहीं लौटाते हैं। वे पॉइंटर्स को संदर्भित करते हैं।और इस प्रकार जब कंटेनर std::algorithms
के साथ प्रयोग किया जाता है, तो एल्गोरिदम संग्रहीत पॉइंटर्स की बजाय संग्रहीत ऑब्जेक्ट्स को प्रतिलिपि बनाने की कोशिश करता है।
एक गलती से अपनी बहुरूपी वस्तुओं गैर copyable बनाने के लिए भूल जाता है, तो उन्हें कॉपी अर्थ विज्ञान स्वचालित रूप से आपूर्ति की जाती है, एक संकलन समय त्रुटि के बजाय एक रन समय त्रुटि में परिणाम:
class Animal
{
public:
Animal() = default;
virtual ~Animal() = default;
virtual void speak() const = 0;
};
कौन सा अब इस गलत परिणाम आउटपुट:
Meow
Baa
Bark
Baa
Meow
Bark
Remove all sheep
destruct Cat
destruct Dog
Meow
Baa
Bark
Baa
destruct Cat
destruct Sheep
destruct Dog
destruct Sheep
vector<unique_ptr>
का उपयोग करते समय यह रन टाइम त्रुटि नहीं हो सकती है।
पॉइंटर्स के कंटेनरों को संग्रहीत करने के प्रतिबाधा विसंगति लेकिन संदर्भों के कंटेनर प्रस्तुत करने से जेनेरिक एल्गोरिदम के साथ कंटेनरों के सुरक्षित उपयोग के साथ बाधाएं दिखाई देती हैं। दरअसल, यही कारण है कि ptr_containers कई एल्गोरिदम के कस्टम संस्करणों के साथ आते हैं।
v.erase_if([](Animal& p)
{return dynamic_cast<Sheep*>(&p);});
आप ptr_containers के सदस्य के रूप आपूर्ति नहीं एक परिवर्तनशील अनुक्रम एल्गोरिथ्म की जरूरत है, उन तक पहुँचने के लिए करने की कोशिश नहीं करते हैं: ptr_containers के साथ इस काम करने के लिए सही तरीका केवल उन सदस्य एल्गोरिदम का उपयोग करने के लिए है <algorithm>
में, या अन्य तृतीय पक्षों द्वारा आपूर्ति किए गए उन सामान्य एल्गोरिदम में।
संक्षेप में, बूस्ट :: ptr_containers ने वास्तविक आवश्यकता को भर दिया जब एकमात्र अन्य व्यावहारिक विकल्प std::vector<boost::shared_ptr<T>>
था। हालांकि अब std::vector<std::unique_ptr<T>>
के साथ, ओवरहेड तर्क चला गया है। और सी ++ 11 समाधान के साथ सुरक्षा और लचीलापन दोनों फायदे हैं। अगर आपको "क्लोन सेमेन्टिक्स" की ज़रूरत है, तो मैं गंभीरता से अपने clone_ptr<T>
लिखने और एसडीडी कंटेनर और एल्गोरिदम के साथ इसका उपयोग करने पर विचार करता हूं।
std :: lib का पुन: उपयोग बूस्ट lib (उदा। Unordered_set/map, forward_list) की तुलना में कंटेनरों के विकल्पों को अधिक खुला रखेगा, और यह आपके विकल्पों को std :: एल्गोरिदम के रूप में यथासंभव चौड़ा रखेगा।
कहा जा रहा है कि, यदि आप काम कर रहे हैं, तो पहले से ही बूस्ट :: ptr_containers का उपयोग कर डीबग कोड, इसे बदलने की कोई जरूरी आवश्यकता नहीं है।
"ओवरहेड तर्क चला गया है" - आज, मैंने वीएस2013-एक्सप्रेस के साथ कुछ परीक्षण किए और आश्चर्यजनक रूप से मुझे 'वेक्टर
दिलचस्प, रिपोर्ट के लिए धन्यवाद। मेरे पास प्रयोग करने के लिए वीएस2013 नहीं है। क्या आकार है (unique_ptr
हाँ, आकार (uq_ptr) == आकार (टी *) == 4./ओ 2 वीएस में "गति के लिए अधिकतम" है। मुझे सूचकांक '[]' पहुंच पर ptr_vector के साथ 50% गति लाभ दिखाई देता है। –
- 1. एसटीएल कंटेनर
- 2. std :: unique_ptr
- 3. स्थिरांक और एसटीएल कंटेनर
- 4. ग्रहण सीडीटी एसटीएल कंटेनर
- 5. एसटीएल-संगत कंटेनर
- 6. एसटीएल कंटेनर तत्व विनाश आदेश
- 7. std :: make_shared, std :: unique_ptr और चाल कंस्ट्रक्टर्स
- 8. एसटीएल कंटेनर की बाइनरी संगतता
- 9. unique_ptr के
- 10. एसटीएल कंटेनर में लगातार संदर्भ
- 11. सी ++ एसटीएल कंटेनर
- 12. आगे एक एसटीएल कंटेनर घोषित करें?
- 13. एसटीएल कंटेनर के साथ unique_ptr का उपयोग करने के लिए यह समझ में आता है? (सी ++ 11)
- 14. एसटीएल का std :: स्ट्रिंग हिस्सा है?
- 15. बढ़ावा :: ptr_container और std :: वेक्टर <shared_ptr>
- 16. std :: unique_ptr को कैसे पास किया जाए?
- 17. ग्रहण सीडीटी अनुक्रमण और std :: unique_ptr
- 18. std :: unique_ptr :: रीसेट और निर्माता अपवाद
- 19. डिस्क-समर्थित एसटीएल कंटेनर कक्षाएं?
- 20. एसटीएल कंटेनर कैसे फोल्ड करें?
- 21. एसटीएल कंटेनर के लिए फॉरवर्ड हेडर
- 22. std :: context_wrapper <T> एक कंटेनर
- 23. कुल एसटीएल कंटेनर मेमोरी खपत को मापने के लिए कैसे?
- 24. कैसे std :: नक्शा कंटेनर
- 25. क्या एसटीएल कंटेनर के बीच तत्वों को हटाने के लिए?
- 26. std :: आवंटक बनाम/बनाम बनाम प्लेसमेंट नया/पी-> ~ टी()
- 27. क्या एसटीएल कंटेनर एडेप्टर के अंतर्निहित कंटेनर तक पहुंचने का कोई तरीका है?
- 28. एसटीएल वेक्टर बनाम नक्शा मिटा
- 29. क्या आप `std :: unique_ifr 'के कंटेनर पर` std :: remove_if` का उपयोग कर सकते हैं?
- 30. std :: size_t बनाम size_t बनाम std :: string :: size_type
'unique_ptr' के साथ आपको अभी भी नोड्स को कम करना होगा, लेकिन इसके अलावा उन्हें बहुत अधिक व्यवहार करना चाहिए। –