Yanıtlar:
Vektörde en az 3 öğe varsa, son 3 öğeyi silmek kolaydır - sadece pop_back'i 3 kez kullanın :
#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';
}
Çıktı:
1 2
İse tanımsız davranış geçmek end()
1-parametresi yineleyici erase()
aşırı. Olmasa bile erase()
, belirtilen öğenin "başında ve sonrasında" olan yineleyicileri geçersiz kılar d
ve 1. döngü yinelemesinden sonra geçersiz kılar .
std::vector
erase()
kaldırılacak bir dizi öğeyi kabul eden 2 parametreli bir aşırı yüklemeye sahiptir. Manuel bir döngüye ihtiyacınız yoktur:
if (X.size() >= 3)
X.erase(X.end()-3, X.end());
İlk olarak, X.end()
bir yineleyiciyi vektörün son öğesine döndürmez, daha çok vektörün son öğesinin ötesindeki öğeye bir yineleyici döndürür, bu da vektörün gerçekte sahip olmadığı bir öğedir, bu yüzden X.erase(d)
program çöktüğünde silin .
Bunun yerine, vektörün en az 3 öğe içermesi koşuluyla, aşağıdakileri yapabilirsiniz:
X.erase( X.end() - 3, X.end() );
Bunun yerine üçüncü son öğeye gider ve bundan sonra her öğeyi silene kadar siler X.end()
.
EDIT: Sadece açıklığa kavuşturmak için, X.end()
başka bir LegacyRandomAccessIterator-
döndüren geçerli bir işlem olması belirtilen bir LegacyRandomAccessIterator olduğunu .
end()
From cppreference'nin tanımı :
Vektör kapsayıcısındaki son öğeyi işaret eden bir yineleyici döndürür.
ve biraz aşağıda:
Herhangi bir öğeye işaret etmez ve bu nedenle kaydı kaldırılamaz.
Başka bir deyişle, vektörün sona eren () hiçbir öğesi yoktur. Bu kaldırma tarafından olmayan eleman silme () yöntemi aracılığıyla, muhtemelen vektörüne ait olmayan bir bellek değiştirmektedir. Dolayısıyla oradan çirkin şeyler olabilir.
“Düşük” değeri ile, [düşük ve yüksek) halinde aralıkları tanımlamak için her zamanki C ++ konvansiyonudur dahil aralığı içinde, ve “yüksek” değeri hariç aralığından.
Şunları kullanabilirsiniz 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;
}
Söylenecek birkaç şey var:
reverse_iterator rit
öğesinin son öğesinde başlar vector X
. Bu konuma denir rbegin
.erase
klasik iterator
çalışmak için gerektirir . Bunu rit
arayarak elde ederiz base
. Ancak bu yeni yineleyici bir sonraki öğeyi rit
ileri yönde gösterecektir .rit
çağırmadan önce base
veerase
Ayrıca hakkında daha fazla bilgi edinmek isterseniz reverse_iterator
, bu yanıtı ziyaret etmenizi öneririm .
Sorudaki bir yorum (şimdi silindi) "yineleyici için operatör yok" ifadesini kullandı. Bununla birlikte, aşağıdaki kod her ikisinde de derlenir ve çalışırMSVC
ve clang-cl
standart ya C++17
da olarak ayarlanır 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;
}
The için sağlanan tanım operator-
aşağıdaki gibidir ( <vector>
başlıkta):
_NODISCARD _Vector_iterator operator-(const difference_type _Off) const {
_Vector_iterator _Tmp = *this;
return _Tmp -= _Off;
}
Ancak, kesinlikle C ++ dil avukatı değilim ve bunun 'tehlikeli' Microsoft uzantılarından biri olması mümkündür. Bunun diğer platformlarda / derleyicilerde işe yarayıp yaramadığını bilmek isterim.
-
bu yineleyiciler için tanımlanmış.
operator-
Yineleyiciler için tanımlanmış olmasa bile , sadece std::advance()
veya std::prev()
yerine kullanabilirsiniz .
Bu açıklama
if (i == 1) X.erase(d);
tanımlanmamış davranışı var.
Ve bu ifade yalnızca son öğeden önceki öğeyi kaldırmaya çalışır
else X.erase(d - i);
çünkü sadece iki yinelemeli bir döngünüz var
for (size_t i = 1; i < 3; i++) {
Aşağıdaki gibi bir şeye ihtiyacınız var.
#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;
}
Program çıktısı
1 2
d
gerçekten yok. Sadece sonunu bulmak için kullanılabilen son bir kanarya değerivector
. Onu kaldıramazsın. Sonra, bir yineleyiciyi sildiğiniz anda, gitti. Daha sonra da dahil olmak üzere hiçbir şey için güvenle kullanamazsınızd - i
.