Aussi agréable que soit le "retour par valeur", c'est le genre de code qui peut conduire à l'erreur. Considérez le programme suivant :
#include <string>
#include <vector>
#include <iostream>
using namespace std;
static std::vector<std::string> strings;
std::vector<std::string> vecFunc(void) { return strings; };
int main(int argc, char * argv[]){
// set up the vector of strings to hold however
// many strings the user provides on the command line
for(int idx=1; (idx<argc); ++idx){
strings.push_back(argv[idx]);
}
// now, iterate the strings and print them using the vector function
// as accessor
for(std::vector<std::string>::interator idx=vecFunc().begin(); (idx!=vecFunc().end()); ++idx){
cout << "Addr: " << idx->c_str() << std::endl;
cout << "Val: " << *idx << std::endl;
}
return 0;
};
- Q : Que se passe-t-il lorsque la commande ci-dessus est exécutée ? R : Un coredump.
- Q : Pourquoi le compilateur n'a-t-il pas détecté l'erreur ? R : Parce que le programme est syntaxiquement, mais pas sémantiquement, correct.
- Q : Que se passe-t-il si vous modifiez vecFunc() pour retourner une référence ? R : Le programme s'exécute jusqu'au bout et produit le résultat attendu.
- Q : Quelle est la différence ? R : Le compilateur ne doit pas n'a pas à créer et à gérer des objets anonymes. Le programmeur a demandé au compilateur d'utiliser exactement un objet pour l'itérateur et pour la détermination du point d'arrivée, plutôt que deux objets différents comme le fait l'exemple brisé.
Le programme erroné ci-dessus n'indiquera aucune erreur même si l'on utilise les options de rapport de GNU g++ -Wall -Wextra -Weffc++.
Si vous devez produire une valeur, alors ce qui suit fonctionnera au lieu d'appeler vecFunc() deux fois :
std::vector<std::string> lclvec(vecFunc());
for(std::vector<std::string>::iterator idx=lclvec.begin(); (idx!=lclvec.end()); ++idx)...
La méthode ci-dessus ne produit pas non plus d'objets anonymes pendant l'itération de la boucle, mais nécessite une éventuelle opération de copie (qui, comme certains le font remarquer, pourrait être optimisée dans certaines circonstances). Mais la méthode de référence garantit qu'aucune copie ne sera produite. Croire que le compilateur effectuera la RVO n'est pas un substitut pour essayer de construire le code le plus efficace possible. Si vous pouvez faire en sorte que le compilateur n'ait pas à effectuer de RVO, vous avez une longueur d'avance.