2011-01-11 13 views
28

क्या यह विभिन्न कंटेनरों से इटरेटर की तुलना करना कानूनी है?विभिन्न कंटेनर से इटरेटर की तुलना

std::vector<int> foo; 
std::vector<int> bar; 

क्या अभिव्यक्ति foo.begin() == bar.begin() झूठी या अपरिभाषित व्यवहार उत्पन्न करती है?

(मैं एक कस्टम इटरेटर लिख रहा हूँ और इस सवाल पर ठोकर खाई, जबकि operator== को लागू करने।)

+0

संबंधित प्रश्न: http://stackoverflow.com/questions/844768/how-is-stl-iterator-equality- स्थापित – jweyrich

उत्तर

29

आप C++ 0x मसौदा पर विचार करें:

§ 24.2.1

एक इटरेटर जे एक पुनरावर्तक से पहुंचा जा सकता कहा जाता है मैं अगर और सिर्फ़ अगर वहाँ के आवेदनों की एक परिमित अनुक्रम है अभिव्यक्ति ++ i जो मुझे == जे बनाता है। यदि जे मैं से पहुंच योग्य है, तो वे एक ही अनुक्रम के तत्वों को संदर्भित करते हैं।

§ 24.2.5

आगे iterators के लिए == के डोमेन समान ही अंतर्निहित अनुक्रम से अधिक iterators का है।

यह देखते हुए कि RandomAccessIterator, सभी आवश्यकताओं को पूरा करना चाहिए ForwardIterator द्वारा लगाए गए विभिन्न कंटेनरों से iterators की तुलना अनिर्धारित रहता है।

+5

+1 विभिन्न कंपाइलरों के व्यवहार का निरीक्षण कभी भी आधिकारिक नहीं रहा है, केवल (पवित्र) मानक पर भरोसा किया जाना चाहिए, और कम से कम सी ++ 0x इसके बारे में सटीक है। –

1

नहीं। अगर यह वैध था, यह अर्थ होगा कि संकेत iterators नहीं होगा।

+0

तो मनमानी पॉइंटर्स की तुलना अवैध है? मैंने सोचा कि केवल पॉइंटर्स घटाने के लिए लागू होगा। – fredoverflow

+0

मुझे यह जवाब नहीं मिला - हो सकता है कि मेरे पास पर्याप्त कॉफी न हो (!) यह वही * प्रकार * है, इसलिए मुझे कल्पना करनी चाहिए कि यह हमेशा झूठी वापसी करता है, लेकिन यूबी (?) – Nim

+0

दो पॉइंटर्स की तुलना नहीं करना चाहिए कानूनी iff (ए) वे दोनों एक ही ऑब्जेक्ट/सरणी को इंगित करते हैं या (बी) उनमें से कम से कम एक पूर्ण है। लेकिन यहां तक ​​कि 'int ए, बी; एक == बी; 'अवैध है। – MSalters

3

आप सीधे विभिन्न कंटेनर से इटरेटर की तुलना नहीं कर सकते हैं। एक इटरेटर एक ऑब्जेक्ट है जो आंतरिक स्थिति का उपयोग करने के लिए एक कंटेनर का उपयोग करता है; एक कंटेनर के इंटीरियर की तुलना किसी दूसरे से तुलना करना समझ में नहीं आता है।

हालांकि, अगर iterators container.begin() से उत्पन्न उपलब्ध हैं, यह मेकअप भावना iterators begin() से वर्तमान इटरेटर मूल्य के लिए चल वस्तुओं की गिनती से तुलना करने के लिए कर सकते हैं। यह std::distance उपयोग किया जाता है:

int a = std::distance(containerA.begin(), iteratorA); 
int b = std::distance(containerB.begin(), iteratorB); 

if (a <comparison> b) 
{ /* ... */ } 

अधिक संदर्भ के बिना, यह न्याय के लिए कि क्या यह आपकी समस्या है या नहीं का समाधान होगा मुश्किल है। YMMV।

+0

"आप नहीं कर सकते" से आपका क्या मतलब है? यह झूठी पैदा करता है? यह संकलित नहीं करता है? यह अपरिभाषित व्यवहार है? इसे कार्यान्वित करना असंभव है? इसका कुछ अर्थ नहीं निकलता? ... – fredoverflow

+1

क्या आपका मतलब मानक या गैर-संवेदना से अस्वीकृत है? –

+0

@Maththieu - मेरा मतलब गैर-संवेदनात्मक था; मैंने सोचा कि मैंने इसे दूसरी सजा में मंजूरी दे दी है! –

0

आईएसओ/आईईसी 14882: 2003 (ई) 5.10.1

== (के बराबर) और = (के बराबर नहीं) एक ही अर्थ प्रतिबंध, रूपांतरण, और परिणाम प्रकार ऑपरेटरों है! रिलेशनशिप ऑपरेटर के रूप में उनकी निचली प्राथमिकता और सत्य-मूल्य परिणाम को छोड़कर। [..] पॉइंटर्स ऑब्जेक्ट्स या उसी प्रकार के फ़ंक्शंस (सूचक रूपांतरण के बाद) की तुलना समानता के लिए की जा सकती है। एक ही प्रकार के दो पॉइंटर्स बराबर तुलना करते हैं यदि केवल और यदि वे दोनों शून्य हैं, तो दोनों एक ही फ़ंक्शन पर इंगित करते हैं, या दोनों एक ही पते (3.9.2) का प्रतिनिधित्व करते हैं।

XCode पर

सिमुलेशन परिणाम (3.2.3):

#include <iostream> 
#include <vector> 

int main() 
{ 
    std::vector <int> a,aa; 
    std::vector <float> b; 

    if(a.begin() == aa.begin()) 
     std::cout << "\n a.begin() == aa.begin() \n" ; 

    a.push_back(10) ; 

    if(a.begin() != aa.begin()) 
     std::cout << "\n After push back a.begin() != aa.begin() \n" ; 

    // Error if(a.begin() == b.begin()) 

    return 0; 
} 

आउटपुट:

a.begin() == aa.begin()
धक्का वापस एक के बाद। शुरू करें()! = aa.begin()

+4

सिर्फ इसलिए कि यह एक विशेष मामले (पॉइंटर्स) के लिए काम करता है इसका मतलब यह नहीं है कि यह सामान्य मामले (इटरेटर) द्वारा गारंटीकृत है। – fredoverflow

+0

लेकिन सवाल * इटरेटर * पॉइंटर्स नहीं था। –

+0

@ कोनराड रुडॉल्फ - इटरेटर्स ऐसा लगता है जैसे वे पॉइंटर अरिथेमेटिक पर काम करते हैं। तो, इटरेटर की तुलना पॉइंटर्स से नहीं की जा सकती है? – Mahesh

0

मुझे मानक 10 से इनपुट इटरेटर पर आवश्यकताएं नहीं मिलती हैं 0%, लेकिन वहां से (आगे/बिडरेक्शनल/यादृच्छिक एक्सेस इटरेटर्स) पर == के डोमेन पर कोई आवश्यकता नहीं है, इसलिए इसे वापसी झूठी परिणामस्वरूप समकक्ष संबंध में परिणाम हो सकता है। आप < या> या विभिन्न कंटेनर से इटरेटर पर घटाव नहीं कर सकते हैं।

संपादित करें: इसे झूठी वापसी की आवश्यकता नहीं है, इसके परिणामस्वरूप समकक्ष संबंध होना चाहिए, यह बराबर तुलना करने के लिए दो खाली कंटेनर के .begin() की अनुमति देता है (जैसा कि किसी अन्य उत्तर में दिखाया गया है)। यदि इटरेटर्स dereferencable हैं, a == b => *a == *b को पकड़ना है। यह अभी भी अपरिभाषित व्यवहार नहीं है।

+2

'आगे इटरेटर्स के लिए == का डोमेन उसी अंतर्निहित अनुक्रम पर इटरेटर का है। § 24.2.5 (सी ++ 0x) – jweyrich

+0

सी ++ 03: मुझे लगता है कि '==' केवल इनपुट इटरेटर्स पर लागू होता है। '==' इनपुट समेककों के लिए इसके डोमेन_ के समकक्ष संबंध होने की आवश्यकता है, लेकिन आगे के पुनरावृत्तियों के लिए और ऊपर '==' एक समकक्ष संबंध होना आवश्यक है ... पूर्ण स्टॉप। –

+0

हां, मैं सी ++ 03 का जिक्र कर रहा था, मुझे नहीं पता कि 0x ड्राफ्ट है। – etarion

4

जहां तक ​​मुझे पता है अपरिभाषित व्यवहार।

/* 
* to disable iterator checking that complains that the iterators are incompatible (come from * different containers :-) 
*/ 
#define _HAS_ITERATOR_DEBUGGING 0 

std::vector<int> vec1, vec2; 

std::vector<int>::iterator it1 = vec1.begin(); 
std::vector<int>::iterator it2 = vec2.begin(); 

if (it1 == it2) 
{ 
std::cout << "they are equal!!!"; 
} 

साथ वी.एस. 2010 में इस मामले में सच :-) में समानता परीक्षण रिटर्न, कंटेनर के बाद से खाली हैं और iterators की _Ptr सदस्य दोनों nullptr हैं।

कौन जानता है कि आपका कार्यान्वयन चीजों को अलग करता है और परीक्षण झूठी वापसी करेगा :-)।

संपादित करें:

देखें C++ Standard library Active Issues list "विभिन्न कंटेनरों के बीच 446 इटरेटर समानता"। शायद कोई यह देखने के लिए मानक जांच सकता है कि परिवर्तन अपनाया गया था या नहीं?

संभवतः यह सक्रिय मुद्दों की सूची पर नहीं है, इसलिए चार्ल्स बेली जिन्होंने इसका उत्तर भी दिया है, यह सही है कि यह अनिर्दिष्ट व्यवहार है।

तो मुझे लगता है कि विभिन्न कार्यान्वयन के बीच व्यवहार भिन्न हो सकता है (कम से कम सैद्धांतिक रूप से) और यह केवल एक समस्या है।

तथ्य यह है कि वीएस चेक के साथ आने वाले एसटीएल कार्यान्वयन में इटरेटर डीबगिंग सक्षम है, इस सटीक मामले (विभिन्न कंटेनरों से आने वाले इटेटर) कम से कम मेरे लिए गायनल्स एक बार और अधिक है कि जब भी संभव हो तो ऐसी तुलना से बचा जाना चाहिए ।

2

मेरा मानना ​​है कि यह अनिर्दिष्ट व्यवहार (सी ++ 03) है। std::vector इटरेटर यादृच्छिक अभिगम इटरेटर हैं और == का व्यवहार अग्रेषित करने वालों की आवश्यकताओं में परिभाषित किया गया है।

== एक तुल्यता संबंध

ध्यान दें कि यह एक प्रकार पर एक आवश्यकता है, इसलिए लागू किया जाना चाहिए (इस मामले में) मान्य (dereferencable या अन्यथा) std::vector::iterator रों के किसी भी जोड़े के लिए है। मेरा मानना ​​है कि इसका मतलब है == आपको true/false उत्तर देना होगा और यूबी का कारण नहीं बन सकता है।

- यदि ए और बी बराबर हैं, तो या तो ए और बी दोनों भरोसेमंद हैं या अन्यथा निराशाजनक नहीं है।

इसके विपरीत, एक अपरिवर्तनीय पुनरावर्तक एक पुनरावर्तक के बराबर तुलना नहीं कर सकता है जो कि भरोसेमंद नहीं है।

- यदि ए और बी दोनों भरोसेमंद हैं, तो एक == बी अगर और केवल अगर * ए और * बी एक ही वस्तु है।

दो पुनरावृत्तियों वाले दो पुनरावृत्तियों के लिए a == b पर आवश्यकता की कमी पर ध्यान दें। इतने लंबे समय के == सकर्मक है के रूप में (यदि a.end() == b.end() और b.end() == c.end() तो a.end() == c.end()), कर्मकर्त्ता (a.end() == a.end()) और सममित (यदि a.end() == b.end() तो b.end() == a.end()) यह कुछ करता है, तो कोई फर्क नहीं पड़ता, सभी या कोई end() विभिन्न कंटेनरों को iterators बराबर की तुलना करें।

नोट, यह भी कि यह < के विपरीत है। < को b - a के संदर्भ में परिभाषित किया गया है, जहां a और b दोनों यादृच्छिक एक्सेस iterators हैं।b - a निष्पादित करने की पूर्व शर्त यह है कि Distance मान n जैसे a + n == b होना चाहिए, जिसके लिए a और b एक ही श्रेणी में इटरेटर होने के लिए आवश्यक है।

+0

मेरा मानना ​​है कि "यदि ए और बी दोनों भरोसेमंद हैं, तो एक == बी अगर और केवल तभी * ए और * बी एक ही वस्तु है"। मैं कहूंगा कि अगर एक == बी' THEN '* एक == * बी' है, लेकिन रिवर्स सामान्य मामले में नहीं है। –

+1

@Matthieu एम .: यह मानक से सीधे आता है। नोट: "एक ही वस्तु है" नहीं * * एक == * बी'। –

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