जवाबों:
यदि वेक्टर में कम से कम 3 आइटम हैं, तो अंतिम 3 आइटम को हटाना सरल है - बस 3 बार pop_back का उपयोग करें :
#include <vector>
#include <iostream>
int main()
{
std::vector<float> v = { 1, 2, 3, 4, 5 };
for (int i = 0; i < 3 && !v.empty(); ++i)
v.pop_back();
for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';
}
आउटपुट:
1 2
1-पैरामीटर अधिभार के लिए पुनरावृत्ति पास करने के लिए यह अपरिभाषित व्यवहार है । यहां तक कि अगर यह नहीं थे, तो पुनरावृत्तियों को अमान्य करता है जो निर्दिष्ट तत्व पर "पहले और बाद में" हैं, 1 लूप पुनरावृत्ति के बाद अमान्य बना रहा है ।end()erase()erase()d
std::vector2-पैरामीटर erase()अधिभार है जो हटाने के लिए तत्वों की एक श्रृंखला को स्वीकार करता है। आपको मैन्युअल लूप की आवश्यकता नहीं है:
if (X.size() >= 3)
X.erase(X.end()-3, X.end());
सबसे पहले, X.end()वेक्टर के अंतिम तत्व के लिए एक पुनरावृत्ति वापस नहीं करता है, यह बल्कि वेक्टर के अंतिम तत्व के पिछले तत्व के लिए एक पुनरावृत्त लौटाता है, जो एक ऐसा तत्व है जो वेक्टर वास्तव में स्वयं का नहीं होता है, इसीलिए जब आप प्रयास करते हैं इसे X.erase(d)प्रोग्राम क्रैश के साथ मिटा दें ।
इसके बजाय, बशर्ते कि वेक्टर में कम से कम 3 तत्व हों, आप निम्न कार्य कर सकते हैं:
X.erase( X.end() - 3, X.end() );
जो बदले में तीसरे अंतिम तत्व तक जाता है, और उसके बाद हर तत्व को मिटा देता है X.end()।
संपादित करें: केवल स्पष्ट करने के लिए, X.end()एक LegacyRandomAccessIterator है जो एक मान्य -ऑपरेशन के लिए निर्दिष्ट है जो एक अन्य LegacyRandomAccessIterator देता है ।
Cppreferenceend() से परिभाषा है:
वेक्टर कंटेनर में अतीत के अंत तत्व का जिक्र करते हुए एक पुनरावृत्ति देता है।
और थोड़ा नीचे:
यह किसी भी तत्व की ओर इशारा नहीं करता है, और इस तरह से इसे समाप्त नहीं किया जाएगा।
दूसरे शब्दों में, वेक्टर का कोई ऐसा तत्व नहीं है जो अंत () को इंगित करता है। उस गैर-तत्व को मिटा देने () विधि के माध्यम से dereferencing करके , आप संभवतः मेमोरी को बदल रहे हैं जो वेक्टर से संबंधित नहीं है। इसलिए बदसूरत चीजें वहां से हो सकती हैं।
अंतराल में शामिल "निम्न" मान और अंतराल से बाहर रखा गया "उच्च" मान के साथ, अंतराल [निम्न, उच्च) के रूप में वर्णन करना सामान्य C ++ सम्मेलन है ।
आप एक का उपयोग कर सकते हैं reverse_iterator:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<float> X = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
// start the iterator at the last element
vector<float>::reverse_iterator rit = X.rbegin();
// repeat 3 times
for(size_t i = 0; i < 3; i++)
{
rit++;
X.erase(rit.base());
}
// display all elements in vector X
for(float &e: X)
cout << e << '\n';
return 0;
}
उल्लेख करने के लिए कुछ चीजें हैं:
reverse_iterator ritके अंतिम तत्व पर शुरू होता है vector X। इस स्थिति को कहा जाता है rbegin।eraseiteratorसाथ काम करने के लिए क्लासिक की आवश्यकता होती है । हमें वह ritकॉल करने से मिलता है base। लेकिन वह नया पुनरावृत्ति ritआगे के दिशा से अगले तत्व को इंगित करेगा ।ritकॉल करने से पहले अग्रिम baseऔरeraseयदि आप इसके बारे में अधिक जानना चाहते हैं reverse_iterator, तो मैं इस उत्तर पर जाने का सुझाव देता हूं ।
प्रश्न में एक टिप्पणी (अब हटा दी गई) में कहा गया है कि "इट्रेटर के लिए कोई संचालक नहीं है।" हालाँकि, निम्न कोड कंपाइल करता है और दोनों में काम करता है MSVCऔर clang-cl, C++17या तो मानक सेट के साथ या C++14:
#include <iostream>
#include <vector>
int main()
{
std::vector<float> X{ 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f };
for (auto f : X) std::cout << f << ' '; std::cout << std::endl;
std::vector<float>::iterator d = X.end();
X.erase(d - 3, d); // This strongly suggest that there IS a "-" operator for a vector iterator!
for (auto f : X) std::cout << f << ' '; std::cout << std::endl;
return 0;
}
इस के लिए प्रदान की गई परिभाषा operator-इस प्रकार है ( <vector>हेडर में):
_NODISCARD _Vector_iterator operator-(const difference_type _Off) const {
_Vector_iterator _Tmp = *this;
return _Tmp -= _Off;
}
हालाँकि, मैं निश्चित रूप से कोई C ++ भाषा-वकील नहीं हूँ, और यह संभव है कि यह उन 'खतरनाक' Microsoft एक्सटेंशनों में से एक है। मुझे यह जानने में बहुत दिलचस्पी होगी कि क्या यह अन्य प्लेटफार्मों / कंपाइलरों पर काम करता है।
-उन प्रकार के पुनरावृत्तियों के लिए परिभाषित किया गया है।
operator-पुनरावृत्तियों के लिए कोई परिभाषित नहीं किया गया था, तो आप बस std::advance()या std::prev()इसके बजाय उपयोग कर सकते हैं ।
यह कथन
if (i == 1) X.erase(d);
अपरिभाषित व्यवहार है।
और यह कथन अंतिम तत्व से पहले केवल तत्व को हटाने की कोशिश करता है
else X.erase(d - i);
क्योंकि आपके पास केवल दो पुनरावृत्तियों के साथ एक लूप है
for (size_t i = 1; i < 3; i++) {
आपको निम्नलिखित की तरह कुछ चाहिए।
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
int main()
{
std::vector<float> v = { 1, 2, 3, 4, 5 };
auto n = std::min<decltype( v.size() )>( v.size(), 3 );
if ( n ) v.erase( std::prev( std::end( v ), n ), std::end( v ) );
for ( const auto &item : v ) std::cout << item << ' ';
std::cout << '\n';
return 0;
}
कार्यक्रम का आउटपुट है
1 2
dवास्तव में मौजूद नहीं है। यह केवल एक का पिछला-अंत-का-कैनरी मूल्य है जिसका अंत केवल खोजने योग्य हैvector। आप इसे हटा नहीं सकते। अगला, जैसे ही आप एक पुनरावृत्ति मिटाते हैं, यह चला गया है। आप किसी भी चीज के लिए बाद में सुरक्षित रूप से इसका उपयोग नहीं कर सकते हैं, जिसमें शामिल हैंd - i।