Dupliquer possible:
C ++ 11 rvalues et confusion sémantique de mouvement
Ce que je pense être correct est
std::ssortingng GetLine() { std::ssortingng str; std::getline(std::cin, str); return std::move(str); }
Mais à ce lien http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html (vérifier la partie d’en-tête Renvoyer une référence explicite à une valeur une fonction)
qui est la recherche n ° 1 dans la recherche sémantique de déplacement montre une signature de fonction similaire à
int&& GetInt() { int x = 0; // code here return std::move(x); }
D’après ce que j’ai lu à d’autres endroits, && signifie rvalue reference . Dans ce cas, il renvoie une référence à un object qui n’existe pas.
Alors c’est quoi?
(Oui, je sais que déplacer un int n’a pas de réel avantage, mais la question est de savoir s’il faut utiliser le type de retour std :: ssortingng ou std :: ssortingng && dans la première fonction. Et si c’est comme cela que cela devrait être fait pour tous les types.)
Vous avez absolument raison de dire que l’exemple int&& GetInt()
est erroné et renvoie une référence à un object détruit. Cependant, à moins que je ne l’aie manquée, le lien que vous avez posté ne montre pas de code renvoyant une référence à une variable locale . Au lieu de cela, je vois une référence à une variable globale renvoyée, ce qui est correct.
Voici comment vous utilisez la sémantique de déplacement lors du retour:
std::ssortingng func() { std::ssortingng rv; /* ... */ return rv; }
En règle générale, vous ne devez pas utiliser std::move()
lors du retour d’un object. La raison en est que le déplacement est déjà implicitement autorisé à tout moment si RVO peut se produire et que l’utilisation de std::move()
supprimera RVO. Donc, utiliser std::move()
ne sera jamais meilleur et sera souvent pire que de revenir normalement.
Encore une fois, utiliser std::move()
peut être pire que de simplement nommer la variable à renvoyer car elle supprime l’optimisation de la valeur de retour. L’optimisation de la valeur de retour permet à un object d’être renvoyé à l’appelant sans qu’il soit nécessaire de le copier.
dans une instruction
return
dans une fonction avec un type de retour de classe, lorsque l’expression est le nom d’un object automatique non volatile (autre qu’un paramètre function ou catch-clause) avec le même type cv-non qualifié que le type de retour de la fonction, l’opération de copie / déplacement peut être omise en construisant l’object automatique directement dans la valeur de retour de la fonction– [class.copy] 12.8 / 31
Mais utiliser std::move()
empêche que l’expression renvoyée soit le nom de l’object que vous renvoyez. Au lieu de cela, l’expression est plus compliquée et le langage n’est plus autorisé à lui donner un traitement spécial.
Nommer l’object n’est pas pire que d’utiliser std::move()
c’est parce qu’il existe une autre règle qui dit qu’une expression peut déjà être traitée comme une valeur rvalue sans avoir besoin de std::move()
.
Lorsque les critères d’élision d’une opération de copie sont remplis ou le seraient, à l’exception du fait que l’object source est un paramètre de fonction et que l’object à copier est désigné par une valeur lvalue, la résolution de surcharge pour sélectionner le constructeur de la copie est d’abord effectué comme si l’object était désigné par une valeur.
Répondant à la question, en quelque sorte: retourne une ssortingng
. Ne move
rien, mais utilisez plutôt (comptez) sur RVO:
std::ssortingng func() { std::ssortingng rv; /* ... */ return rv; }
C’est ainsi que cela devrait être fait en général. Vous ne pouvez pas renvoyer une référence (valeur r ou non) à une référence temporaire.
Pas besoin de dire return std::move(str);
si str
est une variable locale: si la variable satisfait aux critères d’optimisation de la valeur de retour, dans une instruction return
, la variable sera liée à une référence rvalue.
De même, prenez garde de ne pas renvoyer de référence à une variable locale, ni à lvalue ni à la référence rvalue.
Tout compte fait, vous devriez avoir:
int foo() { int x; /*...*/ return x; } std::ssortingng bar() { std::ssortingng str; /*...*/ return str; }