J'ai parcouru cette page mais je ne suis pas en mesure d'en obtenir la même raison. Là, il est mentionné que
"il est plus judicieux pour lui de ne renvoyer aucune valeur et de demander aux clients d'utiliser front () pour inspecter la valeur au début de la file d'attente"
Mais l'inspection d'un élément depuis front () nécessitait également que cet élément soit copié dans lvalue. Par exemple dans ce segment de code
std::queue<int> myqueue;
int myint;
int result;
std::cin >> myint;
myqueue.push (myint);
/ * ici temporaire sera créé sur RHS qui sera affecté au résultat, et dans le cas où si retourne par référence, le résultat sera rendu invalide après l'opération pop * /
result = myqueue.front(); //result.
std::cout << ' ' << result;
myqueue.pop();
sur la cinquième ligne, l' objet cout crée d'abord une copie de myqueue.front () puis l'affecte au résultat. Alors, quelle est la différence, la fonction pop aurait pu faire la même chose.
void std::queue::pop();
).front()
exigeait également que cet élément soit copié dans lvalue" - non, ce n'est pas le cas.front
renvoie une référence, pas une valeur. Vous pouvez inspecter la valeur à laquelle elle fait référence sans la copier.pop()
. Si vous utilisez,std::queue<T, std::list<T>>
il n'y a aucun problème à ce que la référence fourniefront()
soit invalidée par unpush()
. Mais vous devez connaître votre modèle d'utilisation et documenter vos contraintes.Réponses:
Il aurait en effet pu faire la même chose. La raison pour laquelle ce n'est pas le cas, est qu'un pop qui a renvoyé l'élément popped est dangereux en présence d'exceptions (devoir retourner par valeur et donc créer une copie).
Considérez ce scénario (avec une implémentation pop naïve / inventée, pour illustrer mon propos):
Si le constructeur de copie de T lance au retour, vous avez déjà modifié l'état de la file d'attente (
top_position
dans mon implémentation naïve) et l'élément est supprimé de la file d'attente (et non retourné). À toutes fins utiles (quelle que soit la manière dont vous interceptez l'exception dans le code client), l'élément en haut de la file d'attente est perdu.Cette implémentation est également inefficace dans le cas où vous n'avez pas besoin de la valeur sautée (c'est-à-dire qu'elle crée une copie de l'élément que personne n'utilisera).
Cela peut être mis en œuvre de manière sûre et efficace, avec deux opérations distinctes (
void pop
etconst T& front()
).la source
pop
? c'est assez contre-intuitif. Il pourrait être nommédrop
, et alors il est clair pour tout le monde qu'il ne fait pas apparaître l'élément, mais le laisse tomber à la place ...pop
ne rien rendre. Voir par exemple sur wikipedia .La page à laquelle vous avez lié répond à votre question.
Pour citer toute la section pertinente:
C ++ est conçu dans un souci d'efficacité, sur le nombre de lignes de code que le programmeur doit écrire.
la source
pop
dont renvoie une valeur.pop ne peut pas renvoyer une référence à la valeur qui est supprimée, car elle est supprimée de la structure de données, alors à quoi la référence doit-elle faire référence? Il pourrait renvoyer par valeur, mais que faire si le résultat de pop n'est stocké nulle part? Ensuite, du temps est perdu à copier la valeur inutilement.
la source
pop
retours et l'acte de retour peuvent entraîner une exception. Il devrait évidemment supprimer l'élément avant de le renvoyer, et si quelque chose le lance, l'élément pourrait être irrévocablement perdu.value_type
a un constructeur de mouvement nothrow, mais l'interface de la file d'attente serait alors différente selon le type d'objet que vous y stockez, ce qui ne serait pas utile.Avec l'implémentation actuelle, ceci est valide:
Si pop renverrait une référence, comme ceci:
Ensuite, le code suivant pourrait planter, car la référence n'est plus valide:
En revanche, s'il renverrait une valeur directement:
Ensuite, vous devrez faire une copie pour que ce code fonctionne, ce qui est moins efficace:
la source
À partir de C ++ 11, il serait possible d'archiver le comportement souhaité en utilisant la sémantique de déplacement. Comme
pop_and_move
. Le constructeur de copie ne sera donc pas appelé et les performances dépendront uniquement du constructeur de déplacement.la source
pop
exceptions sûres comme par magie .Vous pouvez totalement faire ceci:
Ou, si vous voulez la valeur dans une variable, utilisez une référence:
À côté de cela: le libellé «plus sensible» est une forme subjective de «nous avons examiné les modèles d'utilisation et avons constaté plus de besoin d'une scission». (Rassurez-vous: le langage C ++ n'évolue pas à la légère ...)
la source
Je pense que la meilleure solution serait d'ajouter quelque chose comme
où valeur recevra la valeur sautée.
L'avantage est qu'il pourrait être implémenté en utilisant un opérateur d'assignation de déplacement, tandis que l'utilisation de front + pop fera une copie.
la source