एसटीडी पर वेक्टर :: वेक्टर: बिना हस्ताक्षर किए इंडेक्स चर


469

C ++ में वेक्टर के ऊपर चलने का सही तरीका क्या है?

इन दो कोड अंशों पर विचार करें, यह ठीक काम करता है:

for (unsigned i=0; i < polygon.size(); i++) {
    sum += polygon[i];
}

और ये वाला:

for (int i=0; i < polygon.size(); i++) {
    sum += polygon[i];
}

जो उत्पन्न करता है warning: comparison between signed and unsigned integer expressions

मैं सी ++ की दुनिया में नया हूं, इसलिए unsignedचर मुझे थोड़ा सा भयावह लगता है और मुझे पता है कि unsignedचर का उपयोग खतरनाक हो सकता है यदि सही तरीके से उपयोग नहीं किया जाता है, तो - क्या यह सही है?


9
अहस्ताक्षरित सही है क्योंकि बहुभुज (आकार) अहस्ताक्षरित प्रकार का है। Unsigned का मतलब हमेशा सकारात्मक होता है या 0. यह सब इसका मतलब है। इसलिए यदि चर का उपयोग हमेशा केवल गणना के लिए होता है, तो अहस्ताक्षरित सही विकल्प है।
एडम ब्रुक

2
@AdamBruss उर्फ .size()प्रकार का नहीं है । यह टाइप का है । unsignedunsigned intstd::size_t
अंडरस्कोर_ड

1
@underscore_d size_t अहस्ताक्षरित के लिए एक उपनाम है।
एडम ब्रून

1
@AdamBruss नंबर std::size_tएक _-कार्यान्वयन-परिभाषित टंकण है। मानक देखें। आपके वर्तमान कार्यान्वयन के std::size_tबराबर हो सकता है unsigned, लेकिन यह प्रासंगिक नहीं है। इसे रोकने के परिणामस्वरूप गैर-पोर्टेबल कोड और अपरिभाषित व्यवहार हो सकता है।
अंडरस्कोर_ड

2
@ एलएफ ... यकीन है, जो शायद std::size_tव्यवहार में है। क्या आपको लगता है कि हमने 6 वर्षों में टिप्पणियों के इस जुमले की धारा में अभी तक सब कुछ कवर किया है?
अंडरस्कोर_ड

जवाबों:


816

पीछे की ओर पुनरावृति के लिए यह उत्तर देखें ।

फॉर्वर्ड करना लगभग समान है। बस वृद्धि द्वारा पुनरावृत्तियों / स्वैप गिरावट को बदलें। आपको पुनरावृत्तियों को प्राथमिकता देनी चाहिए। कुछ लोग आपको std::size_tसूचकांक चर प्रकार के रूप में उपयोग करने के लिए कहते हैं । हालाँकि, यह पोर्टेबल नहीं है। हमेशा size_typeकंटेनर के टाइपडेफ का उपयोग करें (जब आप आगे चलने वाले पुनरावृत्ति मामले में केवल एक रूपांतरण के साथ दूर हो सकते हैं, यह वास्तव में पिछड़े पुनरावृत्ति मामले में सभी तरह से गलत हो सकता है std::size_t, जब उपयोग करने की स्थिति std::size_tमें व्यापक है , तो इसका उपयोग क्या है size_type) :


एसटीडी :: वेक्टर का उपयोग करना

पुनरावृत्तियों का उपयोग करना

for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
    /* std::cout << *it; ... */
}

महत्वपूर्ण है, हमेशा पुनरावृत्तियों के लिए उपसर्ग वृद्धि वेतनमान का उपयोग करें जिनकी परिभाषा आपको नहीं पता है। यह आपके कोड को यथासंभव सामान्य सुनिश्चित करेगा।

रेंज C ++ 11 का उपयोग करना

for(auto const& value: a) {
     /* std::cout << value; ... */

सूचकांकों का उपयोग करना

for(std::vector<int>::size_type i = 0; i != v.size(); i++) {
    /* std::cout << v[i]; ... */
}

सरणियों का उपयोग करना

पुनरावृत्तियों का उपयोग करना

for(element_type* it = a; it != (a + (sizeof a / sizeof *a)); it++) {
    /* std::cout << *it; ... */
}

रेंज C ++ 11 का उपयोग करना

for(auto const& value: a) {
     /* std::cout << value; ... */

सूचकांकों का उपयोग करना

for(std::size_t i = 0; i != (sizeof a / sizeof *a); i++) {
    /* std::cout << a[i]; ... */
}

पिछड़े पुनरावृत्ति उत्तर में पढ़ें कि समस्या क्या समस्या sizeofपैदा कर सकती है, हालांकि।


आकार प्रकार के संकेत: अंतर_ प्रकार का उपयोग करना अधिक पोर्टेबल हो सकता है। iterator_traits <element_type *> :: अंतर_type आज़माएं। यह एक घोषणा का एक कौर है, लेकिन यह अधिक पोर्टेबल है ...
विल्हेल्मेल

wilhelmtell, मुझे किस_ अंतर का उपयोग करना चाहिए? sizeof को लौटने के लिए परिभाषित किया गया है size_t :) मैं आपको नहीं समझता। अगर मैं एक-दूसरे से पॉइंटर्स को घटाना था, तो अंतर_ सही विकल्प होगा।
जोहान्स स्काउब -

इस पोस्ट में आपके द्वारा बताई गई तकनीक का उपयोग करने वाले सरणियों पर पुनरावृत्ति कार्य नहीं करेगा यदि उस फ़ंक्शन को किसी फ़ंक्शन पर पास किए गए सरणी पर फ़ंक्शन में प्रदर्शन किया जा रहा है। क्योंकि sizeof array केवल sizeof पॉइंटर लौटाएगा।
सिस्टमफॉल्ट

1
@ नील मैं सहमत हूँ कि अहस्ताक्षरित लूप काउंटर का उपयोग करना एक बुरा विचार है। लेकिन क्योंकि मानक लाइब्रेरी इंडेक्स और आकार के लिए अहस्ताक्षरित पूर्णांक प्रकारों का उपयोग करती है, इसलिए मैं मानक लाइब्रेरी के लिए अहस्ताक्षरित अनुक्रमणिका प्रकारों को प्राथमिकता देता हूं। अन्य पुस्तकालयों के परिणामस्वरूप केवल हस्ताक्षरित प्रकारों का उपयोग किया जाता है, जैसे कि क्यूटी लिब।
जोहान्स शहाब -

32
C ++ 11 के लिए अद्यतन: लूप के लिए आधारित रेंज। for (auto p : polygon){sum += p;}
सियुआन रेन

170

चार साल बीत गए, Google ने मुझे यह जवाब दिया। साथ मानक सी ++ 11 (उर्फ C ++ 0x नया:) वहाँ वास्तव में (पश्चगामी संगतता को तोड़ने की कीमत पर) ऐसा करने का एक नया तरीका है सुखद autoकीवर्ड। यह स्पष्ट रूप से (संकलक के लिए), जो उपयोग करने के लिए टाइप करें (जब पुन: सदिश प्रकार को दोहराते हैं) का उपयोग करने के लिए स्पष्ट रूप से इट्रेटर के प्रकार को निर्दिष्ट करने के दर्द को बचाता है। vअपने होने के साथ vector, आप कुछ इस तरह से कर सकते हैं:

for ( auto i = v.begin(); i != v.end(); i++ ) {
    std::cout << *i << std::endl;
}

C ++ 11 आगे भी जाता है और आपको वैक्टर जैसे संग्रह पर पुनरावृति के लिए एक विशेष वाक्यविन्यास देता है। यह उन चीजों को लिखने की अनिवार्यता को हटा देता है जो हमेशा एक जैसी होती हैं:

for ( auto &i : v ) {
    std::cout << i << std::endl;
}

इसे एक कार्यशील कार्यक्रम में देखने के लिए, एक फ़ाइल बनाएँ auto.cpp:

#include <vector>
#include <iostream>

int main(void) {
    std::vector<int> v = std::vector<int>();
    v.push_back(17);
    v.push_back(12);
    v.push_back(23);
    v.push_back(42);
    for ( auto &i : v ) {
        std::cout << i << std::endl;
    }
    return 0;
}

इसे लिखने के रूप में, जब आप इसे g ++ के साथ संकलित करते हैं, तो आपको अतिरिक्त फ्लैग देकर नए मानक के साथ काम करने के लिए इसे सामान्य रूप से सेट करने की आवश्यकता होती है:

g++ -std=c++0x -o auto auto.cpp

अब आप उदाहरण चला सकते हैं:

$ ./auto
17
12
23
42

कृपया ध्यान दें कि संकलित करने और चलाने के निर्देश लिनक्स पर gnu c ++ संकलक के लिए विशिष्ट हैं , कार्यक्रम मंच (और संकलक) स्वतंत्र होना चाहिए।


7
सी ++ 11 तुम देता हैfor (auto& val: vec)
Flexo

@flexo धन्यवाद, मुझे नहीं पता कि मैं इसे कैसे भूल सकता हूं। पर्याप्त C ++ नहीं कर रहा, मुझे लगता है। विश्वास नहीं हो सकता कि कुछ ऐसा है जो व्यावहारिक था (सोचा था कि वास्तव में जावास्क्रिप्ट सिंटैक्स था)। मैंने इसमें शामिल होने के उत्तर को बदल दिया।
kratenko

आपका जवाब बहुत अच्छा है। यह अनपेक्षित है कि विभिन्न ओएस डेविट में जी ++ का डिफ़ॉल्ट संस्करण 4.3 से कम है जो इसे काम नहीं करता है।
रत्न टाटा

क्या आपको वेक्टर के साथ आरंभ करने की आवश्यकता है std::vector<int> v = std::vector<int>();, या क्या आप std::vector<int> v;इसके बजाय बस इस्तेमाल कर सकते हैं ?
बिल चीथम 13

@BillCheatham वेल - मैंने इसे बिना शुरुआती के लिए आज़माया, और यह काम किया, इसलिए ऐसा लगता है कि यह बिना काम करता है।
क्रेटेंको

44

आपके उदाहरण में विशिष्ट मामले में, मैं इसे पूरा करने के लिए STL एल्गोरिदम का उपयोग करूँगा।

#include <numeric> 

sum = std::accumulate( polygon.begin(), polygon.end(), 0 );

एक अधिक सामान्य के लिए, लेकिन अभी भी काफी सरल मामला है, मैं इसके साथ जाऊंगा:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace boost::lambda;
std::for_each( polygon.begin(), polygon.end(), sum += _1 );

38

जोहान्स शाउब के जवाब के बारे में:

for(std::vector<T*>::iterator it = v.begin(); it != v.end(); ++it) { 
...
}

यह कुछ संकलक के साथ काम कर सकता है लेकिन gcc के साथ नहीं। यहाँ समस्या यह है कि यदि std :: वेक्टर :: iterator एक प्रकार है, तो एक चर (सदस्य) या एक फ़ंक्शन (विधि) है। हमें gcc के साथ निम्नलिखित त्रुटि मिलती है:

In member function void MyClass<T>::myMethod()’:
error: expected `;' before ‘it’
error: ‘it’ was not declared in this scope
In member function ‘void MyClass<T>::sort() [with T = MyClass]’:
instantiated from ‘void MyClass<T>::run() [with T = MyClass]’
instantiated from here
dependent-name ‘std::vector<T*,std::allocator<T*> >::iterator’ is parsed as a non-type, but instantiation yields a type
note: say ‘typename std::vector<T*,std::allocator<T*> >::iterator’ if a type is meant

समाधान बताए गए कीवर्ड 'टाइपनेम' का उपयोग कर रहा है:

typename std::vector<T*>::iterator it = v.begin();
for( ; it != v.end(); ++it) {
...

2
आपको विस्तार से बताना चाहिए कि यह केवल तब लागू होता है जब Tकोई टेम्पलेट तर्क होता है, और इस प्रकार यह अभिव्यक्ति std::vector<T*>::iteratorएक आश्रित नाम है। एक आश्रित नाम को एक प्रकार के रूप में पार्स करने के लिए, इसे typenameकीवर्ड द्वारा पूर्व संकेत दिया जाना चाहिए , क्योंकि डायग्नोस्टिक इंगित करता है।
मोनिका

17

एक कॉल vector<T>::size()प्रकार का मान लौटाता है std::vector<T>::size_type, int नहीं, अहस्ताक्षरित int या अन्यथा।

आम तौर पर C ++ में कंटेनर पर पुनरावृति पुनरावृत्तियों का उपयोग करके किया जाता है , इस तरह।

std::vector<T>::iterator i = polygon.begin();
std::vector<T>::iterator end = polygon.end();

for(; i != end; i++){
    sum += *i;
}

जहां T वेक्टर में आपके द्वारा संग्रहीत डेटा का प्रकार है।

या अलग यात्रा एल्गोरिदम का उपयोग करते ( std::transform, std::copy, std::fill, std::for_eachवगैरह)।


Iterators आम तौर पर एक अच्छा विचार है, हालांकि मुझे संदेह है कि "अंत" को एक अलग चर में संग्रहीत करने की आवश्यकता है और यह सब एक (;;) कथन के अंदर किया जा सकता है।
सौलियस ita एमाईटाइटिस

1
मुझे पता है कि शुरुआत () और अंत () लगातार समय परिशोधन कर रहे हैं, लेकिन मैं आमतौर पर एक पंक्ति में सब कुछ रटना की तुलना में अधिक पठनीय होना चाहता हूं।
जैस्पर बेकर्स

3
पठनीयता में सुधार के लिए आप अलग-अलग लाइनों में विभाजित कर सकते हैं। लूप के बाहर पुनरावृत्तियों को घोषित करने का मतलब है कि आपको विभिन्न प्रकारों के कंटेनरों पर प्रत्येक लूप के लिए एक अलग पुनरावृत्ति नाम की आवश्यकता है।
जय कॉनरोड

मुझे सभी अंतरों के बारे में पता है, और जो मूल रूप से नीचे आता है वह व्यक्तिगत प्राथमिकता है; यह आमतौर पर है कि मैं चीजों को कैसे करता हूं।
जैस्पर बेकर्स

2
@pihentagy मुझे लगता है कि यह फॉर-लूप के पहले खंड में सेट किया जाएगा। जैसे। के लिए (ऑटो i = पॉलीगॉन.बेगिन (), एंड = पॉलीगॉन.एंड (); मैं! = एंड; मैं ++)
जैस्पर बेकर्स

11

उपयोग करें size_t:

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

उद्धरण विकिपीडिया :

Stdlib.h और stddef.h हेडर फाइलें एक डेटाटाइप को परिभाषित size_tकरती हैं, जिसका उपयोग किसी वस्तु के आकार को दर्शाने के लिए किया जाता है। लाइब्रेरी फ़ंक्शंस जो आकार लेते हैं उनसे अपेक्षा करते हैं कि वे प्रकार के हों size_t, और आकार- प्रकार ऑपरेटर उनका मूल्यांकन करता है size_t

वास्तविक प्रकार का size_tप्लेटफ़ॉर्म-निर्भर है; आम गलती यह है कि size_tअहस्ताक्षरित int के समान है, जो प्रोग्रामिंग त्रुटियों को जन्म दे सकता है, विशेष रूप से 64-बिट आर्किटेक्चर अधिक प्रचलित हो जाते हैं।


वेक्टर के लिए size_t ठीक है, क्योंकि यह सभी वस्तुओं को एक सरणी में संग्रहीत करना चाहिए (स्वयं एक ऑब्जेक्ट, भी) लेकिन एक std :: सूची में size_t तत्वों से अधिक हो सकता है!
MSALERS

1
size_t आम तौर पर एक प्रक्रिया के पता स्थान में सभी बाइट्स की गणना करने के लिए पर्याप्त है। हालांकि मैं देख सकता हूं कि कुछ विदेशी वास्तुशिल्प पर यह कैसे नहीं हो सकता है, मैं इसके बारे में चिंता नहीं करूंगा।

AFAIK यह करने के लिए अनुशंसा की जाती है #include <cstddef>के बजाय <stddef.h>या बुरा, की सम्पूर्णता [c]stdlib, और उपयोग std::size_tके बजाय अयोग्य संस्करण - जहां के बीच एक विकल्प है किसी भी अन्य स्थिति के लिए और एक ही <cheader>और <header.h>
अंडरस्कोर_ड

7

इतिहास का हिस्सा:

यह दर्शाने के लिए कि संख्या नकारात्मक है या नहीं, कंप्यूटर 'साइन' बिट का उपयोग करता है। intएक हस्ताक्षरित डेटा प्रकार है जिसका अर्थ है कि यह सकारात्मक और नकारात्मक मान (लगभग -2 बिलियन से 2 बिलियन) हो सकता है। Unsignedकेवल धनात्मक संख्याओं को संग्रहीत कर सकता है (और चूंकि यह मेटाडेटा पर थोड़ा बर्बाद नहीं करता है, यह अधिक: 0 से लगभग 4 बिलियन तक संग्रहीत कर सकता है)।

std::vector::size()unsignedकैसे एक वेक्टर एक नकारात्मक लंबाई हो सकता है के लिए एक रिटर्न ?

चेतावनी आपको बता रही है कि आपकी असमानता के बयान का सही संचालन अधिक डेटा और फिर बाईं ओर पकड़ सकता है।

अनिवार्य रूप से यदि आपके पास 2 बिलियन प्रविष्टियों के साथ एक वेक्टर है और आप एक पूर्णांक का उपयोग इंडेक्स में करते हैं तो आप ओवरफ्लो की समस्या से जूझेंगे (इंट लगभग नकारात्मक 2 बिलियन तक वापस आ जाएगा)।


6

मैं आमतौर पर BOOST_FACHACH का उपयोग करता हूं:

#include <boost/foreach.hpp>

BOOST_FOREACH( vector_type::value_type& value, v ) {
    // do something with 'value'
}

यह एसटीएल कंटेनर, एरेज़, सी-स्टाइल स्ट्रिंग्स आदि पर काम करता है।


2
किसी अन्य प्रश्न का अच्छा उत्तर (मुझे वेक्टर को कैसे पुनरावृत्त करना चाहिए?), लेकिन पूरी तरह से ऐसा नहीं है जो ओपी पूछ रहा था (एक अहस्ताक्षरित चर के बारे में चेतावनी का अर्थ क्या है?)
abelenky

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

5

पूरा होने के लिए, C ++ 11 सिंटैक्स पुनरावृत्तियों ( रेफरी ) के लिए केवल एक और संस्करण को सक्षम करता है :

for(auto it=std::begin(polygon); it!=std::end(polygon); ++it) {
  // do something with *it
}

जो रिवर्स इटरेशन के लिए भी आरामदायक है

for(auto it=std::end(polygon)-1; it!=std::begin(polygon)-1; --it) {
  // do something with *it
}

5

C ++ 11 में

मैं सामान्य एल्गोरिदम का उपयोग करना चाहूंगा for_eachताकि अतिरिक्त नामांकित कार्यों / वस्तुओं से बचने के लिए सही प्रकार के इटरेटर और लैम्ब्डा अभिव्यक्ति की खोज न हो।

आपके विशेष मामले के लिए छोटा "सुंदर" उदाहरण (बहुभुज को पूर्णांक का एक वेक्टर है):

for_each(polygon.begin(), polygon.end(), [&sum](int i){ sum += i; });

पर परीक्षण किया गया: http://ideone.com/i6Ethd

शामिल करने के लिए मत भूलना : एल्गोरिथ्म और, ज़ाहिर है, वेक्टर :)

Microsoft वास्तव में इस पर भी एक अच्छा उदाहरण है:
स्रोत: http://msdn.microsoft.com/en-us/library/dd293608.aspx

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main() 
{
   // Create a vector object that contains 10 elements.
   vector<int> v;
   for (int i = 1; i < 10; ++i) {
      v.push_back(i);
   }

   // Count the number of even numbers in the vector by 
   // using the for_each function and a lambda.
   int evenCount = 0;
   for_each(v.begin(), v.end(), [&evenCount] (int n) {
      cout << n;
      if (n % 2 == 0) {
         cout << " is even " << endl;
         ++evenCount;
      } else {
         cout << " is odd " << endl;
      }
   });

   // Print the count of even numbers to the console.
   cout << "There are " << evenCount 
        << " even numbers in the vector." << endl;
}

4
for (vector<int>::iterator it = polygon.begin(); it != polygon.end(); it++)
    sum += *it; 

2
वेक्टर के लिए यह ठीक है, लेकिन आम तौर पर यह ++ के बजाय ++ का उपयोग करना बेहतर होता है, अगर इटिलेटर स्वयं गैर-तुच्छ है।
स्टीव जेसोप

व्यक्तिगत रूप से, मुझे ++ i का उपयोग करने के लिए उपयोग किया जाता है, लेकिन मुझे लगता है कि ज्यादातर लोग i ++ शैली पसंद करते हैं ("के लिए" के लिए डिफ़ॉल्ट वीएस कोड स्निपेट है I ++)। बस एक विचार
मेहरदाद अफश्री

@MehrdadAfshari कौन परवाह करता है "अधिकांश लोग" क्या करते हैं? "अधिकांश लोग" बहुत सारी चीजों के बारे में गलत हैं। पोस्ट-इंक / डिक्रीमेंट जहां पूर्व मूल्य का उपयोग कभी नहीं किया जाता है वह गलत और अक्षम है, कम से कम सिद्धांत में - चाहे वह कितनी बार नेत्रहीन रूप से सब-बराबर उदाहरण कोड में उपयोग किया जाए। आपको बुरी प्रथाओं को प्रोत्साहित नहीं करना चाहिए ताकि चीजें उन लोगों से अधिक परिचित हों जो अभी तक बेहतर नहीं जानते हैं।
अंडरस्कोर_ड

2

पहला प्रकार सही है, और कुछ सख्त अर्थों में सही है। (यदि आप सोचते हैं कि आकार कभी भी शून्य से कम नहीं हो सकता है।) यह चेतावनी मुझे अच्छे उम्मीदवारों में से एक के रूप में नजरअंदाज करती है, हालांकि।


2
मुझे लगता है कि इसे नजरअंदाज किया जाना एक भयानक उम्मीदवार है - इसे ठीक करना आसान है, और एक बार थोड़ी देर में वास्तविक कीड़े अनुचित रूप से हस्ताक्षरित / अहस्ताक्षरित मूल्यों की तुलना करने वाली त्रुटियों के कारण होते हैं। उदाहरण के लिए, इस मामले में, यदि आकार INT_MAX से अधिक है तो लूप कभी समाप्त नहीं होता है।
स्टीव जेसोप

... या शायद यह तुरंत समाप्त हो जाए। दोनों में से एक। निर्भर करता है कि क्या हस्ताक्षरित मूल्य तुलना के लिए अहस्ताक्षरित में बदल गया है, या अहस्ताक्षरित को हस्ताक्षरित में बदल दिया गया है। 32bit int के साथ 64 बिट प्लेटफॉर्म पर, हालांकि win64 की तरह, int को size_t में बढ़ावा दिया जाएगा, और लूप समाप्त हो जाएगा।
स्टीव जेसोप

@SteveJessop: आप निश्चितता के साथ नहीं कह सकते कि लूप कभी खत्म नहीं होता है। पुनरावृति पर i == INT_MAX, तब i++अपरिभाषित व्यवहार का कारण बनता है। इस बिंदु पर कुछ भी हो सकता है।
बेन वोइगट

@BenVoigt: सच है, और अभी भी चेतावनी को नजरअंदाज करने के लिए आधार प्रदान नहीं करता है :-)
स्टीव जेसप

2

इस बात पर विचार करें कि क्या आपको इसकी पुनरावृति की आवश्यकता है

<algorithm>मानक हेडर इस लिए सुविधाओं के साथ हमें प्रदान करता है:

using std::begin;  // allows argument-dependent lookup even
using std::end;    // if the container type is unknown here
auto sum = std::accumulate(begin(polygon), end(polygon), 0);

एल्गोरिथ्म लाइब्रेरी में अन्य कार्य सामान्य कार्य करते हैं - सुनिश्चित करें कि आप जानते हैं कि क्या उपलब्ध है यदि आप खुद को प्रयास करना चाहते हैं।


1

अस्पष्ट लेकिन महत्वपूर्ण विवरण: यदि आप कहते हैं "के लिए (यह ऑटो)" निम्नानुसार, आप वस्तु की एक प्रति प्राप्त करते हैं, न कि वास्तविक तत्व:

struct Xs{int i} x;
x.i = 0;
vector <Xs> v;
v.push_back(x);
for(auto it : v)
    it.i = 1;         // doesn't change the element v[0]

वेक्टर के तत्वों को संशोधित करने के लिए, आपको एक संदर्भ के रूप में पुनरावृत्त को परिभाषित करने की आवश्यकता है:

for(auto &it : v)

1

यदि आपका कंपाइलर इसका समर्थन करता है, तो आप वेक्टर तत्वों तक पहुंचने के लिए एक सीमा का उपयोग कर सकते हैं:

vector<float> vertices{ 1.0, 2.0, 3.0 };

for(float vertex: vertices){
    std::cout << vertex << " ";
}

प्रिंट: 1 2 3। ध्यान दें, आप वेक्टर के तत्वों को बदलने के लिए इस तकनीक का उपयोग नहीं कर सकते।


0

दो कोड सेगमेंट समान काम करते हैं। हालाँकि, अहस्ताक्षरित int "मार्ग सही है। अहस्ताक्षरित int प्रकारों का उपयोग आपके द्वारा उपयोग किए गए इंस्टेंस में वेक्टर के साथ बेहतर काम करेगा। वेक्टर पर आकार () सदस्य फ़ंक्शन को अहस्ताक्षरित पूर्णांक मान देता है, इसलिए आप चर की तुलना करना चाहते हैं। "I" अपने स्वयं के प्रकार के मूल्य के लिए।

इसके अलावा, यदि आप अभी भी इस बारे में थोड़ा असहज हैं कि आपके कोड में "अहस्ताक्षरित int" कैसा दिखता है, तो "uint" आज़माएं। यह मूल रूप से "अहस्ताक्षरित int" का छोटा संस्करण है और यह बिल्कुल उसी तरह काम करता है। आपको इसका उपयोग करने के लिए अन्य शीर्षलेखों को शामिल करने की भी आवश्यकता नहीं है।


आकार के लिए अनइंस्टॉल किए गए पूर्णांक () आवश्यक रूप से C ++ शब्दों में "अहस्ताक्षरित int" के बराबर नहीं है, अक्सर इस मामले में 'अहस्ताक्षरित पूर्णांक' 64bit अहस्ताक्षरित पूर्णांक है जबकि 'अहस्ताक्षरित int' आमतौर पर 32bit है।
मेड्रान

0

इसे जोड़ने के रूप में मैं इसे किसी भी उत्तर में उल्लिखित नहीं पा सका: सूचकांक-आधारित पुनरावृत्ति के लिए, हम इसका उपयोग कर सकते हैं decltype(vec_name.size())जो इसका मूल्यांकन करेगाstd::vector<T>::size_type

उदाहरण

for(decltype(v.size()) i{ 0 }; i < v.size(); i++) {
    /* std::cout << v[i]; ... */
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.