सूचकांक चर के प्रकार का चयन


11

हम अधिकांश समय इंटेगर प्रकार का प्रतिनिधित्व सूचकांक चर का उपयोग करते हैं। लेकिन कुछ स्थितियों में, हमें चुनने के लिए मजबूर किया जाता है

std::vector<int> vec;
....

for(int i = 0; i < vec.size(); ++i)
....

यह संकलक को चेतावनी को बढ़ाने का कारण होगा जो हस्ताक्षरित / अहस्ताक्षरित चर का मिश्रित उपयोग करता है। अगर मैं इंडेक्स चर बनाता हूं for( size_t i = 0; i < vec.size(); i++ ), (या ए unsigned int) तो यह मुद्दों को सुलझा देगा।

जब यह विंडोज़ प्रकारों का उपयोग करने के लिए और अधिक विशिष्ट हो जाता है, तो अधिकांश विंडोज एपीआई DWORD के साथ काम कर रहे हैं (जो कि टाइप किए गए एफ़डी-एड के रूप में)।

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

DWORD dwCount;
....

for(DWORD i = 0; i < dwCount; ++i)
....

मुझे यह थोड़ा अजीब लगता है। यह समस्या हो सकती है।

मैं मानता हूं कि हम उसी तरह के इंडेक्स वैरिएबल का उपयोग करने वाले हैं जिससे कि इंडेक्स वैरिएबल के साथ रेंज की समस्याएं हो सकें। उदाहरण के लिए यदि हम उपयोग कर रहे हैं

_int64 i64Count; // 
....

for(_int64 i = 0; i < i64Count; ++i)
....

लेकिन DWORD, या अहस्ताक्षरित पूर्णांक के मामले में, इसे फिर से लिखने में कोई समस्या है

for(int i = 0; (size_t)i < vec.size(); ++i)

अधिकांश लोग समान मुद्दों के साथ कैसे काम कर रहे हैं?


4
आप इंडेक्स का प्रतिनिधित्व करने के लिए एक हस्ताक्षरित पूर्णांक का उपयोग क्यों करेंगे? यह स्ट्रिंग को संग्रहीत करने के लिए पूर्णांक के वेक्टर का उपयोग करने जैसा है।
Šमोन तोथ

3
@Let_Me_Be: क्योंकि यह सीमा की स्थितियों को परखना आसान बनाता है। उदाहरण के लिए, शून्य से नीचे की गणना पर, लूप बॉडी को निष्पादित करने से पहले एक कम-से-कम परीक्षण एक अहस्ताक्षरित मान के साथ काम नहीं कर सकता है। इसी तरह अधिकतम तक गिनती काम नहीं करती है। बेशक उस मामले में एक हस्ताक्षरित पूर्णांक या तो काम नहीं करेगा (क्योंकि यह इतने बड़े मूल्य का प्रतिनिधित्व नहीं कर सकता है)।
२०

"यह संकलक को चेतावनी को बढ़ाने का कारण होगा जो हस्ताक्षरित / अहस्ताक्षरित चर का मिश्रित उपयोग करता है।" यह केवल दो समस्याओं में से एक है जिसके साथ आपको मुकाबला करना होगा। कई मामलों std::size_tमें इंट (या उससे भी लंबे) की तुलना में एक उच्च रैंक है। यदि वेक्टर का आकार कभी भी अधिक std::numeric_limits<int>::max()हो जाता है, तो आपको int का उपयोग करने पर पछतावा होगा।
एड्रियन मैकार्थी

जवाबों:


11

वेक्टर में एक टाइपराइफ होता है जो आपको उपयोग करने का सही प्रकार बताता है: -

for(std::vector<int>::size_type i = 0; i < thing.size(); ++i)
{
}

यह लगभग हमेशा size_t परिभाषित किया जाता है, लेकिन आप उस पर भरोसा नहीं कर सकते


8
वास्तव में पठनीयता में सुधार नहीं, IMHO।
डॉक्टर ब्राउन

नहीं, लेकिन जैसा कि यह बताने का एकमात्र तरीका है कि वेक्टर में एक इंडेक्स के लिए उपयोग करने का सही प्रकार क्या है, यह वास्तव में मायने नहीं रखता है ...
JohnB

4
इन दिनों c ++ 11 में ऑटो का उपयोग करें
JohnB

6
@ जॉन आपको पसंद है auto i = 0? यह बिल्कुल मदद नहीं करता है, iएक बन गया int
ज़ीनत

1
पठनीयता में सुधार किया जा सकता है using index_t = std::vector<int>::size_type;
टोबे स्पाइट

4
std::vector<int> vec;

for(int i = 0; i < vec.size(); ++i)

इसके लिए एक इटरेटर का प्रयोग करें, forलूप का नहीं ।

दूसरों के लिए, जब तक चर प्रकार एक ही आकार के है, static_castठीक से काम करना चाहिए (यानी DWORDकरने के लिए int16_t)


2
for (std::vector<int>::iterator i = vec.begin(); i != vec.end(); ++i)लिखने के लिए एक दर्द है। होने for (auto i = vec.begin();...एक पूरी बहुत अधिक पठनीय है। बेशक, foreachसी ++ 11 में भी है।
डेविड थार्नले

3

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

for( size_t i = 0; i < vec.size(); i++ )

या

for( int i = 0; i < (int)vec.size(); i++ )

(बेशक, उत्तरार्द्ध केवल जब कुछ अंतर अतिप्रवाह होने का कोई खतरा नहीं है)।


3

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

आपके उदाहरण में (तुलना intकरने के लिए size_t), जब तक कि किसी भी तरह से बड़ी सीमा न हो, तब तक इसे संक्षेप में intबदल दिया जाएगा । इस प्रकार, यदि ऋणात्मक है, तो यह संभावित रूप से उस मूल्य से अधिक होगा जो आप इसे रैपराउंड के कारण तुलना कर रहे हैं। यदि आपकी अनुक्रमणिका ऋणात्मक नहीं है तो यह एक समस्या नहीं होगी, लेकिन फिर भी आपको वह चेतावनी मिल जाएगी।size_tintsize_tint

इसके बजाय, एक अहस्ताक्षरित प्रकार है (जैसे के रूप में उपयोग unsigned int, size_tया, के रूप में जॉन बी सिफारिश की गई है , std::vector<int>::size_typeअपने सूचकांक चर के लिए):

for(unsigned int i = 0; i < vec.size(); i++)

हालांकि, नीचे गिनती करते समय सावधान रहें:

for(unsigned int i = vec.size()-1; i >= 0; i--) // don't do this!

ऊपर काम नहीं करेगा क्योंकि अहस्ताक्षरित i >= 0होने पर हमेशा सत्य होता iहै। इसके बजाय, छोरों को गिनने के लिए " एरो ऑपरेटर " का उपयोग करें :

for (unsigned int i = vec.size(); i-- > 0; )
    vec[i] = ...;

जैसा कि अन्य उत्तर बताते हैं, आप आम तौर पर एक यात्रा करने वाले का उपयोग करना चाहते हैं vector। यहाँ C ++ 11 सिंटैक्स है:

for (auto i = vec.begin(); i != vec.end(); ++i)

1
यह अभी भी जोखिम है कि unsigned intआकार धारण करने के लिए पर्याप्त बड़ा नहीं है।
एड्रियन मैकार्थी

2

C ++ 11 के लिए एक नया विकल्प, आप निम्न की तरह काम कर सकते हैं

for(decltype(vec.size()) i = 0; i < vec.size(); ++i) {...}

तथा

for(decltype(dWord) i = 0; i < dWord; ++i) {...}

हालांकि यह मूल-लूप की तुलना में थोड़ा अधिक दोहराता है, यह मानों को निर्दिष्ट करने के पूर्व -11 तरीकों के रूप में लंबे समय से घुमावदार नहीं है, और इस पैटर्न का लगातार उपयोग करना सबसे अधिक काम करेगा, यदि सभी संभव नहीं हैं, तो संभव है के खिलाफ तुलना करना चाहते हैं, जो कोड रीफैक्टरिंग के लिए इसे महान बनाता है। यह इस तरह के सरल मामलों के लिए भी काम करता है:

int x = 3; int final = 32; for(decltype(final) i = x; i < final; ++i)

इसके अलावा, जब आपको उपयोग करना चाहिए autoजब भी आप iकुछ बुद्धिमान मूल्य (जैसे vec.begin()) के decltypeलिए सेट कर रहे हैं , तब काम करता है जब आप शून्य जैसे किसी स्थिरांक पर सेट होते हैं, जहां ऑटो बस यह निर्धारित करेगा intक्योंकि 0 एक सरल पूर्णांक शाब्दिक है।

ईमानदार होने के लिए, मैं autoलूप इंक्रीमेंटर्स के लिए टाइप-निर्धारण का विस्तार करने के लिए एक कंपाइलर तंत्र देखना चाहूंगा, जिसकी तुलना में मूल्य को देखा जाए।


1

मैं इंट का उपयोग करता हूं, जैसे कि for (int i = 0; i < (int)v.size(); ++i)। हाँ, यह बदसूरत है। मैं इसे मानक पुस्तकालय के बेवकूफ डिजाइन पर दोष देता हूं जहां उन्होंने आकार का प्रतिनिधित्व करने के लिए अहस्ताक्षरित पूर्णांक का उपयोग करने का निर्णय लिया। (क्रम में .. क्या? सीमा को एक बिट से बढ़ाएं?)


1
किस स्थिति में नकारात्मक चीज़ों का संग्रह आकार सार्थक होगा? विभिन्न संग्रह आकारों के लिए अहस्ताक्षरित पूर्णांक का उपयोग करना मेरे लिए समझदार विकल्प की तरह लगता है। आखिरी बार मैंने जाँच की, एक स्ट्रिंग की लंबाई लेने से शायद ही कभी कोई नकारात्मक परिणाम लौटा हो ...
एक CVn

1
किस परिस्थिति में यह सरल परीक्षण के लिए सार्थक होगा जैसे कि if(v.size()-1 > 0) { ... }खाली कंटेनर के लिए सच लौटना? समस्या यह है कि आकार का उपयोग अक्सर अंकगणित, एस्प में भी किया जाता है। सूचकांक आधारित कंटेनरों के साथ, जो दिए गए मुसीबत के लिए पूछ रहा है कि वे अहस्ताक्षरित हैं। मूल रूप से, 1) बिटवाइज जोड़तोड़, या 2) के अलावा किसी और चीज के लिए अहस्ताक्षरित प्रकारों का उपयोग करना परेशानी को बुलावा देता है।
zvrba

2
अच्छी बात। हालांकि मैं वास्तव में आपके विशेष उदाहरण के बिंदु को नहीं देखता (मैं शायद सिर्फ इसलिए लिखूंगा if(v.size() > 1) { ... }कि इरादा और अधिक स्पष्ट हो जाता है, और एक अतिरिक्त बोनस के रूप में हस्ताक्षरित / अहस्ताक्षरित का मुद्दा शून्य हो जाता है), मैं देखता हूं कि कुछ विशिष्ट मामलों में कैसे हस्ताक्षर उपयोगी हो सकते हैं। मुझे सही साबित होना है।
एक सीवीएन

1
@ माइकल: मैं मानता हूं कि यह उदाहरण से वंचित था। फिर भी, मैं अक्सर नेस्टेड छोरों के साथ एल्गोरिदम लिखता हूं: (i = 0; मैं <v.size () - 1; ++ i) के लिए (j = i + 1; j <v.size (); ++ j); .. यदि v रिक्त है, तो बाहरी लूप -1 (size_t) -1 बार निष्पादित होता है। इसलिए मुझे या तो हस्ताक्षर किए हुए प्रकार के लूप या कास्ट v.size () से पहले v.empty () की जांच करनी होगी, जो कि मुझे लगता है कि दोनों व्यक्तिगत रूप से बदसूरत वर्कअराउंड हैं। मैं एक कास्ट का चयन करता हूं क्योंकि यह कम LOC है, नहीं तो () s => गलती के लिए कम possibilites। (इसके अलावा, 2 पूरक में, रूपांतरण oveflow एक नकारात्मक संख्या देता है, इसलिए लूप बिल्कुल भी निष्पादित नहीं होता है।)
zvrba

सीमा को 1 बिट से बढ़ाकर (और जारी है) 16-बिट सिस्टम में बहुत उपयोगी था।
एड्रियन मैकार्थी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.