2015-11-23 21 views
5
#include <iostream> 
#include <map> 

int main(int argc, char** argv) 
{ 
    std::map<int, int> map; 
    map.emplace(1, 1); 
    auto reverse_iter = map.rbegin(); 
    std::cout << reverse_iter->first << ", " << reverse_iter->second << std::endl; 
    map.emplace(2, 2); 
    std::cout << reverse_iter->first << ", " << reverse_iter->second << std::endl; 

    return 0; 
} 

यह बाहर प्रिंट:क्या यह उचित व्यवहार है? std :: नक्शा iterator अमान्यकरण

1, 1 
2, 2 

यह वास्तव में क्या होने चाहिए था है, मानक के अनुसार? मैं रिवर्स_आईटर को छू नहीं रहा हूं लेकिन जिस बिंदु पर यह इंगित कर रहा है वह बदल रहा है। मैंने सोचा था कि std :: मानचित्र में iterators सम्मिलन के खिलाफ सुरक्षित होना चाहिए था। फिर भी ऐसा लगता है कि रिवर्स_इटर उस मूल्य को इंगित करने के लिए नहीं है जिसे मैंने बताया था, "इस बिंदु पर मानचित्र के अंत में जो भी हो रहा है" के बजाय।

अद्यतन: आगे की जानकारी, यदि यह मायने रखती है: यह आगे इटरेटर्स (किसी भी स्थिति में मुझे लगता है) के साथ ऐसा प्रतीत नहीं होता है, और मेरा जीसीसी संस्करण 5.1.1-4 है।

+0

"अवैध" होने के नाते और इशारा करते हुए के लिए नए डेटा एक ही बात नहीं हैं, वे कर रहे हैं? यह आपके कंटेनर में आखिरी जोड़ी के लिए एक वैध सूचक है। वह जोड़ी बस बदल गई है। – tadman

+0

आगे इटरेटर्स के साथ नहीं होता है। शुरूआत के साथ rbegin बदलें और (2, 2) (0, 0) के साथ प्रतिस्थापित करें। और फिर, क्या मानकों का अनुपालन है? क्योंकि यह वास्तव में अप्रत्याशित रूप से खराब है, यह निश्चित रूप से है। – KarenRei

+0

ठीक है, मानचित्र में डाली गई पहली चीज़ बदलेगी नहीं। हालांकि आखिरी चीज आपने किया था। – tadman

उत्तर

3

यहाँ उद्धृत http://en.cppreference.com/w/cpp/container/map/rbegin

रिवर्स इटरेटर भंडार पुनरावर्तक एक यह वास्तव में

पक्ष प्रभाव होगा को संदर्भित करता है की तुलना में अगले तत्व के रूप में है कि आप उस iterator से पहले कुछ सम्मिलित करता है, तो (अंत में)()) आप उस नए मान को देखेंगे जब आप रिवर्स इटेटरेटर को अस्वीकार करते हैं। मुझे नहीं लगता कि इस मामले में रिवर्स इटरेटर को अमान्य कर दिया गया है।

+0

तो, मूल रूप से, यह डिजाइन द्वारा तोड़ दिया गया है? : Þ आपके द्वारा उपयोग किए जाने वाले पुनरावर्तक के बगल में कुछ ऐसा परिवर्तन उस इटरेटर को बदल सकता है जिसका आप उपयोग कर रहे हैं? ग्रेट ...: Þ लेकिन, यदि मानक कहता है, तो मैं कुछ भी नहीं कर सकता। – KarenRei

+0

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

+0

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

4

सी ++ मानक के अनुसार (23.2.4 साहचर्य कंटेनरों)

9 डालने और सदस्यों क़ायम करना iterators और कंटेनर के लिए संदर्भ की वैधता को प्रभावित नहीं करेगा, और मिटा सदस्यों करेगा केवल रद्द इटरेटर्स और मिटाए गए तत्वों के संदर्भ।

दूसरी ओर (24.5.1 रिवर्स iterators)

1 कक्षा टेम्पलेट reverse_iterator पुनरावर्तक अनुकूलक कि अनुक्रम के शुरुआत करने के लिए उसके अंतर्निहित इटरेटर द्वारा परिभाषित के अंत से iterates है वह अनुक्रम

हालांकि अंतिम उद्धरण में कक्षा std::reverse_iterator के बारे में कहा गया है, यह मानक कंटेनर के रिवर्स इटरेटर्स के लिए मान्य है।

तालिका 97 के अनुसार - प्रतिवर्ती कंटेनर आवश्यकताओं

rbegin()reverse_iterator(end())

तो अपने उदाहरण में रिवर्स इटरेटर अभी भी end() से मेल खाती है से मेल खाती है। `

1

map.rbegin() पुनरावर्तक कि std::reverse_iterator(map.end());

के बराबर है रिटर्न समस्या पैदा होती है जब आप एक रिवर्स इटरेटर भिन्नता। जब आप reverse_iterator को अव्यवस्थित करते हैं तो आपको वास्तव में प्राप्त होने वाला मान reverse_iterator के अंदर संग्रहीत होने से पहले इटेटरेटर से मिलता है। यह अजीब लग सकता है, लेकिन अच्छे कारणों से है, और यह अपरिहार्य है।ऐसा इसलिए है, एक सीमा के पिछले-अंत तत्व की व्यवस्था करने के लिए: एक पुनरावर्तक, एक सीमा में एक अतीत-अंत-अंत तत्व को इंगित करता है, जब उलट होता है, तो अंतिम तत्व (इसके पीछे नहीं) को इंगित करता है सीमा (यह उल्टा सीमा का पहला तत्व होगा)। और यदि किसी श्रेणी में पहले तत्व के लिए एक पुनरावर्तक उलट दिया जाता है, तो उलट तत्व पुनरावर्तक पहले तत्व से पहले तत्व को इंगित करता है (यह उल्टा सीमा का अतीत-अंत तत्व होगा)।

यही है, आपके मामले में जब reverse_iter अपसंदर्भन कर के साथ बराबर है:

*(--map.end()); 

नतीजतन, दूसरा emplace के बाद नक्शे के अंतिम तत्व बदल गया है और अपसंदर्भन है (--map.end()) (यानी, अपने reverse_iter) आप मानचित्र में नया अंतिम तत्व प्राप्त करें।

0
std::map<int, int> map2; 
map2.emplace(2, 2); 
auto fiter = map2.begin(); 
std::cout << fiter->first << ", " << fiter->second << std::endl; 
map2.emplace(1, 1); 
std::cout << fiter->first << ", " << fiter->second << std::endl; 
fiter = map2.begin(); 
std::cout << fiter->first << ", " << fiter->second << std::endl; 

प्रिंट

2, 2 
2, 2 
1, 1 
संबंधित मुद्दे