Eu tenho um vetor Eu preciso excluir os três últimos elementos nele. Descreveu essa lógica. O programa trava. Qual poderia ser o erro?
vector<float>::iterator d = X.end();
for (size_t i = 1; i < 3; i++) {
if (i == 1) X.erase(d);
else X.erase(d - i);
}
d
realmente não existe. É o valor canário de um passado-final que pode ser usado apenas para encontrar o fim dovector
. Você não pode removê-lo. Em seguida, assim que você apaga um iterador, ele desaparece. Você não pode usá-lo com segurança posteriormente para qualquer coisa, inclusived - i
.Respostas:
Se houver pelo menos 3 itens no vetor, excluir os 3 últimos itens é simples - basta usar pop_back 3 vezes:
Resultado:
fonte
É um comportamento indefinido passar o
end()
iterador para aerase()
sobrecarga de 1 parâmetro . Mesmo se não fosse,erase()
invalida os iteradores "no e depois" do elemento especificado, tornandod
inválido após a primeira iteração do loop.std::vector
possui umaerase()
sobrecarga de 2 parâmetros que aceita um intervalo de elementos para remover. Você não precisa de um loop manual:Demonstração ao vivo
fonte
Primeiro,
X.end()
não retorna um iterador para o último elemento do vetor, mas retorna um iterador para o elemento após o último elemento do vetor, que é um elemento que o vetor realmente não possui, é por isso que quando você tenta apague-o comX.erase(d)
o programa trava.Em vez disso, desde que o vetor contenha pelo menos três elementos, você pode fazer o seguinte:
Que, em vez disso, vai para o terceiro último elemento e apaga todos os elementos depois até chegar a
X.end()
.EDIT: Apenas para esclarecer,
X.end()
é um LegacyRandomAccessIterator que está especificado para ter uma-
operação válida que retorna outro LegacyRandomAccessIterator .fonte
A definição de
end()
from cppreference é:e um pouco abaixo:
Em outras palavras, o vetor não possui nenhum elemento para o qual end () aponte. Ao desreferenciar esse não elemento através do método erase (), você possivelmente está alterando a memória que não pertence ao vetor. Daí coisas feias podem acontecer a partir daí.
É a convenção usual do C ++ descrever intervalos como [baixo, alto), com o valor "baixo" incluído no intervalo e o valor "alto" excluído do intervalo.
fonte
Você pode usar um
reverse_iterator
:Há poucas coisas a serem mencionadas:
reverse_iterator rit
começa no último elemento dovector X
. Esta posição é chamadarbegin
.erase
requer clássicoiterator
para trabalhar. Nós conseguimos issorit
ligandobase
. Mas esse novo iterador apontará para o próximo elemento derit
frente.rit
antes de ligarbase
eerase
Além disso, se você quiser saber mais
reverse_iterator
, sugiro visitar esta resposta .fonte
Um comentário (agora excluído) na pergunta afirmou que "não existe operador para um iterador". No entanto, o código a seguir compila e funciona em ambos
MSVC
eclang-cl
, com o padrão definido comoC++17
ouC++14
:A definição fornecida para
operator-
é a seguinte (no<vector>
cabeçalho):No entanto, certamente não sou advogado da linguagem C ++ e é possível que essa seja uma daquelas extensões 'perigosas' da Microsoft. Eu ficaria muito interessado em saber se isso funciona em outras plataformas / compiladores.
fonte
-
são definidos para esses tipos de iteradores.operator-
definido para os iteradores, você pode simplesmente usarstd::advance()
ou emstd::prev()
vez disso.Esta afirmação
tem comportamento indefinido.
E esta declaração tenta remover apenas o elemento antes do último elemento
porque você tem um loop com apenas duas iterações
Você precisa de algo como o seguinte.
A saída do programa é
fonte