#include<vector>
#include<iostream>
using namespace std;

int main()
{
    vector<int> vec = {1,2,3,4};
    for(auto & it = vec.begin(); it != vec.end(); ++it)
    {
        cout << *it << endl;
    }
}

Bonjour à tous, en C ++ j'utilise iterator par référence comme "auto & it" et le compilateur renvoie l'erreur

"erreur: initialisation non valide d'une référence non-const de type '__gnu_cxx :: __ normal_iterator> &' à partir d'une rvalue de type 'std :: vector :: iterator {aka __gnu_cxx :: __ normal_iterator>}' pour (auto & it = vec. begin (); it! = vec.end (); ++ it) ".

Je sais que "auto it = vec.begin ()" fonctionne bien, mais comme nous le savons tous, le passage par référence améliorera l'efficacité en C ++, alors pourquoi cette erreur se produit lorsque j'utilise "auto & it"?

6
MA Shengjing 24 juil. 2017 à 09:11

2 réponses

Meilleure réponse

alors pourquoi cette erreur se produit lorsque j'utilise "auto & it"?

Voir le type de retour de begin. Il ne renvoie pas de référence. Il renvoie l'itérateur par valeur. Par conséquent, la valeur de retour est temporaire dans la catégorie rvalue. Les temporaires (rvalues) ne peuvent pas être liées à des références de lvalue non const. C'est ce que signifie l'erreur " initialisation invalide d'une référence non-const de type ... à partir d'une rvaleur de type ... ".

De plus, modifier le pointeur begin du conteneur n'aurait guère de sens. Il aurait été idiot pour begin de renvoyer une référence.

Solution: créez simplement une copie de l'itérateur en déclarant une valeur sans référence, comme vous le savez, fonctionne correctement.

mais comme nous le savons tous, le passage par référence améliorera l'efficacité en C ++

Ça n'a pas de sens. Il est peu probable qu'une référence placée de manière arbitraire améliore l'efficacité. De plus, vous n'essayez pas de transmettre une référence ici. Vous essayez de lier une référence à un objet renvoyé par une fonction.

Presque, sinon toujours, les itérateurs sont très rapides à copier (std::vector::iterator l'est certainement) et l'indirection que vous pouvez potentiellement introduire avec une référence peut bien être moins efficace.

15
eerorika 24 juil. 2017 à 07:36

Le std::vector::begin renvoie une rvalue (un objet temporaire). Vous ne pouvez pas prendre de référence à un objet temporaire avec auto& (référence non-const lvalue). Si vous souhaitez prendre la valeur de retour mentionnée par référence, vous pouvez utiliser auto&& au lieu de auto& mais je ne le recommande pas.

L'utilisation de auto&& créera une référence rvalue mutable à la valeur de retour de std::vector::begin. Cela prolongera sa durée de vie mais je recommande d'utiliser {{X2} } seulement.

L'utilisation de références rvalue n'améliorera pas l'efficacité de votre code, le compilateur optimisera la copie / déplacement de l'objet interateur renvoyé de std::vector::begin par valeur.

4
Akira 24 juil. 2017 à 08:39