#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"?
2 réponses
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.
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.
De nouvelles questions
c++
C ++ est un langage de programmation à usage général. Il a été conçu à l'origine comme une extension de C et a une syntaxe similaire, mais c'est maintenant un langage complètement différent. Utilisez cette balise pour les questions sur le code (à être) compilé avec un compilateur C ++. Utilisez une balise spécifique à la version pour les questions liées à une révision standard spécifique [C ++ 11], [C ++ 14], [C ++ 17], [C ++ 20] ou [C ++ 23], etc. .