web-dev-qa-db-fra.com

Peut-on augmenter un itérateur de plusieurs positions sans la fonction 'avance'?

Je sais que nous pouvons utiliser la fonction advance() pour incrémenter l'itérateur. Nous utilisons également iterator++ pour augmenter l'itérateur d'une position. Pourquoi nous ne pouvons pas utiliser it+=2?

int main()
{
    list<int> l1{1, 2, 3, 5, 6};
    list<int> l2{2, 6, 8};
    auto it = l1.begin();
    advance(it, 2);         //works
    it++;                   //works
    // it+=2;                  //not work
    l2.splice(l2.begin(), l1, it);

    for(int a: l2) cout<<a<<" ";
    cout<<endl;

    return 0;
}

Vous pouvez exécuter le code ci-dessus ici .

16
Lusha Li

operator += n'est pris en charge que par RandomAccessIterator ; notez qu'il est censé avoir une complexité constante.

L'itérateur de std::list est BidirectionalIterator , qui ne prend pas en charge operator +=. (L'itérateur de std::vector et std::array est RandomAccessIterator.)

Notez que les deux pourraient être utilisés avec std :: advance , lorsqu'ils sont utilisés pour RandomAccessIterator, la complexité est constante; lorsqu'il est utilisé pour d'autres InputIterators (y compris BidirectionalIterator), la complexité est linéaire. Cela signifie utiliser std::advance est une bonne idée car elle est plus générale et pourrait bénéficier automatiquement des avantages de RandomAccessIterator.

30
songyuanyao

Vous ne pouvez pas utiliser += 2 avec cet itérateur car dans le cas général, l'incrémentation std::list<> l'itérateur par une valeur arbitraire est une opération relativement inefficace. += n'est pas défini pour votre type d'itérateur spécifiquement pour vous empêcher d'utiliser négligemment/inconsciemment cette opération inefficace dans votre code. Au lieu de cela, si vous voulez vraiment le faire, vous êtes censé utiliser std::advance, qui est une fonction "drapeau rouge" destinée à souligner le fait que vous faites probablement quelque chose d'inefficace. std::advance est principalement destiné à l'esquisse de code ou à peu probable à obtenir code de secours. Vous n'êtes pas censé utiliser gratuitement std::advance dans le code de production. Si vous vous retrouvez soudainement à compter sur std::advance, cela signifie que vous devrez probablement repenser vos structures de données. Fondamentalement, std::advance est comme un casting - évitez-le sauf si vous avez une très très très bonne raison de l'utiliser.

Vous pouvez également utiliser std::next

it = std::next(it, 2);

Cette fonction est beaucoup plus facile à utiliser que std::advance. Par défaut, cette fonction est conçue pour faire avancer l'itérateur d'un pas en avant, mais vous pouvez spécifier le deuxième paramètre pour le déplacer plus loin. Encore une fois, lorsque la valeur du deuxième paramètre est non constante et potentiellement grande, elle doit être considérée comme une fonction "drapeau rouge". Une valeur constante de 2 est certainement dans des limites acceptables.

15
AnT