Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

type de retour

3 réponses
Avatar
thierry nivon
bonjour,
je suis en train de me poser une question assez trivial :
Si je déclare une fonction qui retourne un string par exemple,
est-ce qu'il est plus judicieux de déclarer

string toto()

ou bien

const string & toto()


quels sont les avantages et inconvénients
des deux méthodes

amicalement,
Thierry

3 réponses

Avatar
Wang Zangkun
Le Fri, 28 Oct 2005 20:17:24 +0200, thierry nivon a écrit :

bonjour,
je suis en train de me poser une question assez trivial :
Si je déclare une fonction qui retourne un string par exemple,
est-ce qu'il est plus judicieux de déclarer

string toto()

ou bien

const string & toto()


quels sont les avantages et inconvénients
des deux méthodes

amicalement,
Thierry


quand tu as la fonction string toto(), il y a recopie du résultat
renvoyé par toto; tu peux donc renvoyer une variable locale à la
fonction toto.

avec string& toto(), tu renvoies une référence, ça ne peut donc pas
être une variable locale à toto. Il n'y a pas recopie du résultat, donc
tu économise un tout petit peu en temps et en mémoire, mais pour une
string ça doit pas avoir beaucoup d'effet.

Maintenant, que ce soit const string&, je crois que cela veut dire que tu
ne peux plus modifier le résultat de toto. Le seul avantage reste ici la
non recopie de la valeur.

(avec un string& toto, tu peux faire du toto() = "a", ou appeler une
méthode de la classe string sur la fonction toto, mais c'est plus très
beau, ni compréhensible ni forcément intéressant).

Avatar
kanze
thierry nivon wrote:

je suis en train de me poser une question assez trivial :
Si je déclare une fonction qui retourne un string par exemple,
est-ce qu'il est plus judicieux de déclarer

string toto()

ou bien

const string & toto()


Ça dépend de ce que tu veux faire.

Si tu veux renvoyer une référence à une chaîne existante, il
faut utiliser le deuxième forme. Ce cas arrive surtout quand la
référence n'est pas const : toto est, par exemple, une fonction
membre d'un objet qui contient une chaîne, et tu veux que le
client puisse modifier la chaîne de l'objet. À titre d'exemple :
std::vector< std::string >::operator[]( size_t ) ;
On peut aussi vouloir renvoyer une référence quand il s'agit
d'un type « entité », c-à-d un type où l'identité joue un rôle
(et qui typiquement ne peut pas être copié).

On renvoie par valeur si ce qu'on veut renvoyer est une valeur
et que le client n'a pas besoin d'en connaître la providence. Et
que le client est libre à faire ce qu'il veut avec l'objet
renvoyé, sans que ça influe sur l'objet d'origine.

quels sont les avantages et inconvénients des deux méthodes


Elles font des choses différentes. Si tu as une chaîne (comme
membre, élément, variable globale, etc.), et tu veux donner au
client accès à cette chaîne, il faut renvoyer une référence. Si
tu veux renvoyer une valeur, éventuellement calculée à la volée,
pour que le client en fasse ce qu'il veut, il faut renvoyer une
valeur.

En général, renvoyer une référence donne un couplage fort entre
toi et le client -- le client a accès à tes éléments internes.
Dans certains cas, comme les collections, c'est ce qu'on veut.
Mais en règle générale, si on ne sait pas d'office, c'est la
valeur qui doit prévaloir.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Avatar
kanze
Wang Zangkun wrote:

je suis en train de me poser une question assez trivial : Si
je déclare une fonction qui retourne un string par exemple,
est-ce qu'il est plus judicieux de déclarer

string toto()

ou bien

const string & toto()

quels sont les avantages et inconvénients des deux méthodes


quand tu as la fonction string toto(), il y a recopie du
résultat renvoyé par toto; tu peux donc renvoyer une variable
locale à la fonction toto.


Ou une valeur calculée à la volée, du genre :
return dirname + '/' + filename + ".cc" ;

avec string& toto(), tu renvoies une référence, ça ne peut
donc pas être une variable locale à toto. Il n'y a pas recopie
du résultat, donc tu économise un tout petit peu en temps et
en mémoire, mais pour une string ça doit pas avoir beaucoup
d'effet.


Surtout, la sémantique est différente.

Maintenant, que ce soit const string&, je crois que cela veut
dire que tu ne peux plus modifier le résultat de toto. Le seul
avantage reste ici la non recopie de la valeur.

(avec un string& toto, tu peux faire du toto() = "a", ou
appeler une méthode de la classe string sur la fonction toto,
mais c'est plus très beau, ni compréhensible ni forcément
intéressant).


Ça dépend. Tu rejetterais quelque chose comme :

std::vector< std::string > v ;
// ...
v.at( i ) = "xyz" ;

?

Tout dépend de la sémantique.

En revanche, il faut se méfier beaucoup de l'histoire de gagner
une copie avec std::string const&. Parce que bon gré mal gré, on
expose des détails de l'implémentation, et on limite
l'utilisation. Donc, si par la suite, je modifie le code pour
que la valeur soit calculée, je suis obligé aussi de modifier
l'interface, et déclencher la récompilation de tous mes clients.
Et évidemment, si le client veux faire quelque chose du genre :

std::string completePath
= getFilename().insert( 0, currentDir + '/' ) ;

il ne peut pas.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34