2013-05-25 4 views
11

std::priority_queue::top एक स्थिर मूल्य देता है। हालांकि, मैं प्राथमिकता कतार से शीर्ष तत्व को हटाना चाहता हूं और इसे कहीं और संशोधित करने में सक्षम हूं।उपयोगकर्ता परिभाषित वस्तुओं के साथ प्राथमिक_queue से गैर-कॉन्स टॉप तत्व कैसे प्राप्त करें?

priority_queue<SomeClass, vector<SomeClass>, SomeClassCompare > pQueue; 
... 
SomeClass *toBeModified = &(pQueue.top()); 
pQueue.pop(); 
toBeModified->setMember(3); // I would like to do this 

वहाँ एक रास्ता मैं एक प्राथमिकता कतार से शीर्ष तत्व प्राप्त कर सकते हैं (और कतार से निकालने के लिए) और इसे संशोधित रूप में मैं चाहता हूँ है?

उत्तर

13

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

भले ही top() आपको गैर-const का संदर्भ वापस कर देगा, तो जैसे ही आप कतार से तत्व को हटाते हैं, वैसे ही यह संदर्भ खतरनाक हो जाएगा, और इसके संदर्भ में इसे अपरिभाषित व्यवहार में परिणाम मिलेगा।

यह कहा अपने आंतरिक आदेश के साथ std::priority_queue रिटर्न आप आप खिलवाड़ (जानबूझकर या अनजाने में) से रोकने के लिए const के लिए एक संदर्भ - यह बहुत ज्यादा एक ही कारण नहीं है क्यों इस तरह के std::map और std::set के रूप में साहचर्य कंटेनरों की कुंजी const है ।

SomeClass obj = pQueue.top(); 
pQueue.pop(); 
obj.setMember(42); 
pQueue.push(std::move(obj)); // You can move obj into the queue if you no more need it 

आप हैं:

आप क्या कर सकते हैं, बजाय,, top() द्वारा दिए गए मान के प्रतिलिपि निर्माण करने के लिए है कि नकल, संशोधित करने, मूल हटाने, और कतार में प्रति धक्का है दूसरी तरफ संदर्भ अर्थशास्त्र की आवश्यकता है, तो आपको कतार में संभवतः पॉइंटर्स धक्का (संभावित रूप से स्मार्ट पॉइंटर्स, आपके उपयोग के मामले के आधार पर) को धक्का देना होगा और उचित कस्टम ऑर्डरिंग मानदंड प्रदान करना होगा जो उन पॉइंटर्स को गुणों के आधार पर ऑर्डर करेगा वे वस्तुओं को इंगित करते हैं।

इस मामले में, सावधान रहें कि उन गुणों को रन-टाइम पर संशोधित न करें जिससे वे अपना ऑर्डर अलग कर सकें। यह "कंटेनर" के आंतरिक क्रम के साथ गड़बड़ कर देगा, और इसके परिणामस्वरूप अपरिभाषित व्यवहार होगा।

+2

@Ethouris आपने पूरे बयान "पूर्ण बीएस" लेबलिंग की गलती की है। जो लगभग उसी कारण से विडंबनापूर्ण रूप से गलत है जिसे आप "बकवास" पर हमला करते हैं। – sehe

+1

@Ethouris: कृपया अनावश्यक आक्रामकता से बचें। असहमत होने के लिए और अधिक सुरुचिपूर्ण तरीके हैं। मेरा मुद्दा था (मुझे लगता है, यह 2.5 साल हो गया है) जो तत्व मानक कंटेनरों से धकेलते हैं और हटा दिए जाते हैं, तो ओपी क्या करना चाहता है (कंटेनर के अंदर तत्व का संदर्भ प्राप्त करें, तत्व को हटाएं, संकेत दें) अमान्य है - यूबी में परिणाम। यह आपके द्वारा उल्लेख किए गए सभी अन्य कंटेनर जैसी प्राथमिकता कतारों पर लागू होता है - 'कतार'। मैं यह नहीं कह रहा हूं कि प्राथमिकता कतार इस संबंध में विशेष हैं। –

+1

@Ethouris: इसके अलावा, प्राथमिकता कतारों के संदर्भ में प्राथमिकता कतारों का संदर्भ अमान्यता से कोई लेना देना नहीं है: जैसा कि उत्तर में बताया गया है, इसका कारण है कि उपयोगकर्ता को आंतरिक आदेश मानदंड के साथ गड़बड़ करने से रोकें। –

1

मुझे नहीं लगता कि मूल्य अर्थशास्त्र यहां कम से कम भूमिका निभाते हैं। अन्य सभी कंटेनरों में समान मूल्य अर्थशास्त्र होता है और लगभग सभी उनमें front() प्रदान करने योग्य संदर्भ प्रदान करते हैं।

priority_queuetop() तत्व के संशोधन को अस्वीकार करने का एक सटीक कारण है: ऐसा इसलिए है क्योंकि विशेष तत्व शीर्ष पर है क्योंकि इसके अनुसार वर्तमान मूल्य के अनुसार यह योग्यता प्राप्त है। प्राथमिकता कतार में तत्व कतार के लिए कॉन्फ़िगर किए गए तुलना मानदंडों के अनुसार हमेशा क्रमबद्ध होते हैं (डिफ़ॉल्ट रूप से ऑपरेटर <)। तत्व को बदलकर आप संभावित रूप से इस स्थिति को नष्ट कर सकते हैं और कारण यह है कि सॉर्ट किए गए पूर्व शर्त का उपयोग करने वाले सभी संचालन अपरिभाषित व्यवहार का कारण बनेंगे।

संक्षेप में, कारण है कि priority_queue निहित तत्वों को संशोधित करने की अनुमति नहीं है वास्तव में set और map के लिए कुंजी के मामले में के रूप में ही है।

मैं समझता हूं कि आपके पास कुछ समर्पित तुलना विधि हो सकती है, आप उस फ़ील्ड का उपयोग करते हैं जिसमें तुलना करने के लिए मूल्य शामिल है, और आप इस क्षेत्र को छोड़कर ऑब्जेक्ट की किसी भी सामग्री को संशोधित करने जा रहे हैं। इस तरह आप क्रमबद्ध क्रम की आवश्यकता का उल्लंघन नहीं करते हैं।

  1. अपने वर्ग के कुछ हिस्सों कि mutable के रूप में संशोधित किया जाना चाहिए बनाओ: दो चीजें आप कर सकते हैं। इस तरह आप top() द्वारा तत्व प्राप्त कर सकते हैं और म्यूटेबल सामग्री को संशोधित कर सकते हैं, भले ही यह स्थिर है।

  2. std::priority_queue प्राप्त करके अपनी प्राथमिकता कतार कक्षा बनाएं। इसमें c नामक एक क्षेत्र है (संरक्षित अनुभाग), जिसमें अंतर्निहित कंटेनर का संदर्भ शामिल है - और अंतर्निहित कंटेनर के बजाय हमेशा front() विधि है जो top()priority_queue में उसी तत्व को एक्सेस करती है। अपनी सुरक्षा के लिए, आपको अपना मुख्य क्षेत्र const बनाना चाहिए, ताकि यह निर्माण के दौरान सेट हो और कभी भी बदला न जाए - केवल जोखिम को कम करने के लिए।

आह, और इस समस्या को पॉइंटर्स का उपयोग करके भी हल नहीं किया जा सकता है - पॉइंट ऑब्जेक्ट बिल्कुल वही स्थिर होगा। ये "संदर्भ अर्थशास्त्र" भी आपकी मदद नहीं करेंगे क्योंकि यदि आप एक समर्पित तुलना विधि चाहते हैं, तो इसे वस्तुओं की सामग्री को देखना होगा, और इस तरह आपको बिल्कुल वही समस्या होगी। यदि आप सूचक मूल्यों की तुलना करने पर भरोसा करते हैं, तो यह आपकी मदद करेगा, लेकिन मुझे संदेह होगा कि यह 99% मामलों का समाधान हो सकता है।

+1

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

+0

ठीक है, मैंने पॉइंटर्स के बारे में टिप्पणी को थोड़ा सा बदल दिया। – Ethouris

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