Voici mon code:
while (it!=s.end()) //here 's' is a set of stl and 'it' is iterator of set
{
*it=*it-sub; //'sub' is an int value
it++;
}
Je ne peux pas mettre à jour la valeur de set by iterator. Je veux soustraire une valeur entière «sub» de tous les éléments de l'ensemble.
Quelqu'un peut-il m'aider là où se trouve le problème réel et quelle serait la solution réelle?
Voici le message d'erreur:
error: assignment of read-only location ‘it.std::_Rb_tree_const_iterator<int>::operator*()’
28 | *it=*it-sub;
| ~~~^~~~~~~~
*it - sub
. Veuillez noter questd::set::erase()
renvoie un nouvel itérateur qui doit être utilisé dans votre cas pour que lawhile
boucle fonctionne correctement.Réponses:
Les valeurs clés des éléments dans a
std::set
sontconst
pour une bonne raison. Les modifier peut détruire l'ordre qui est essentiel pour astd::set
.Par conséquent, la solution consiste à effacer l'itérateur et à en insérer un nouveau avec la clé
*it - sub
. Veuillez noter questd::set::erase()
renvoie un nouvel itérateur qui doit être utilisé dans votre cas pour que la boucle while fonctionne correctement.Production:
Démo en direct sur coliru
Les changements en cours d'
std::set
itération ne sont pas un problème en général mais peuvent provoquer des problèmes subtils.Le fait le plus important est que tous les itérateurs utilisés doivent être conservés intacts ou ne plus être utilisés. (C'est pourquoi l'itérateur actuel de l'élément d'effacement est affecté avec la valeur de retour
std::set::erase()
qui est soit un itérateur intact ou la fin de l'ensemble.)Bien sûr, des éléments peuvent également être insérés derrière l'itérateur actuel. Bien que ce ne soit pas un problème concernant le,
std::set
cela peut casser la boucle de mon exemple ci-dessus.Pour le démontrer, j'ai un peu modifié l'exemple ci-dessus. Veuillez noter que j'ai ajouté un compteur supplémentaire pour accorder la fin de la boucle:
Production:
Démo en direct sur coliru
la source
std::set
. Il peut être nécessaire de considérer le cas frontière que le nouvel itérateur est inséré directement derrière l'effacé. - Il sera ignoré après insertion dans la boucle.extract
noeuds, modifier leurs clés et les retourner dans set. Il serait plus efficace, car il évite les allocations inutiles.std::set
. Étant donné que vous ne pouvez pas avoir le même élément deux fois, l'insertion laissera simplementstd::set
inchangé et vous perdrez l'élément ultérieurement. Considérez par exemple l'ensemble d'entrée:{10, 20, 30}
avecadd = 10
.Simple à remplacer simplement par un autre ensemble
la source
Vous ne pouvez pas muter des éléments de
std::set
par conception. Voirhttps://en.cppreference.com/w/cpp/container/set/begin
C'est parce que l'ensemble est trié . Si vous mutez un élément dans une collection triée, la collection doit être triée à nouveau, ce qui est bien sûr possible, mais pas la manière C ++.
Vos options sont:
std::set
, modifiez-le, puis réinsérez-le. (Ce n'est pas une bonne idée si vous souhaitez modifier chaque élément)la source
A
std::set
est généralement implémenté comme un arbre binaire à équilibrage automatique dans STL.*it
est la valeur de l'élément qui est utilisé pour ordonner l'arbre. S'il était possible de le modifier, la commande deviendrait invalide donc il n'est pas possible de le faire.Si vous souhaitez mettre à jour un élément, vous devez trouver cet élément dans l'ensemble, le supprimer et insérer la valeur mise à jour de l'élément. Mais puisque vous devez mettre à jour les valeurs de tous les éléments, vous devez alors effacer et insérer tous les éléments un par un.
Il est possible de le faire en une seule boucle fournie
sub > 0
.S.erase(pos)
supprime l'itérateur en positionpos
et renvoie la position suivante. Sisub > 0
, la valeur mise à jour que vous insérerez viendra avant la valeur au nouvel itérateur dans l'arborescence mais sisub <= 0
, alors la valeur mise à jour viendra après la valeur au nouvel itérateur dans l'arborescence et donc vous vous retrouverez dans un boucle infinie.la source
L'erreur explique à peu près le problème
Les membres du
std::set
conteneur sontconst
. Les modifier annule leur commande respective.Pour changer des éléments dans
std::set
, vous devrez effacer l'élément et le réinsérer après l'avoir changé.Vous pouvez également utiliser
std::map
pour surmonter ce scénario.la source