OVH Cloud OVH Cloud

référence ou pointeur ?

24 réponses
Avatar
Jarod
Selon vous, dans quel(s) cas est il préférable d'utiliser un pointeur et
dans quel(s) cas vaut-il mieux utiliser une référence ?
(en supposant qu'on ne veux pas faire de passage par valeur pour éviter la
copie de l'objet)
En fait, je pose cette question pour le passage d'un argument et pour la
variable d'une classe (il y a donc 2 questions).
Merci

4 réponses

1 2 3
Avatar
Andre Heinen
On Thu, 23 Jun 2005 17:59:37 +0200, "Pierre Lairez"
wrote:

Le Thu, 23 Jun 2005 09:44:22 +0200, Andre Heinen a
écrit:

On Wed, 22 Jun 2005 22:15:30 +0200, "Pierre Lairez"
wrote:

A chaque fois que tu te le demande, utilise des références


Je ne dirais pas ça. Par exemple, je me souviens d'un temps où je me
demandais si, dans les conteneurs de la bibliothèque standard, il
valait mieux utiliser des références ou des pointeurs. Si j'avais
suivi ton raisonnement, j'aurais utilisé des références, et ça
n'aurait pas marché.


Si la solution avec les références ne pouvait pas fonctionner, avais-tu le
choix ?


Non, mais je croyais l'avoir. Je dirais donc, non pas "dans le doute,
utilise une référence", mais "dans le doute, renseigne-toi".

c'est plus sûr
(les références invalides n'existent pas)



<snip>


Ce que tu as voulu dire, c'est qu'étant donné l'obligation
d'initialiser une référence dès sa définition, il est plus rare
d'avoir des erreurs de ce genre avec des références qu'avec des
pointeurs. Elles sont donc plus sûres. Et là, naturellement, je suis
entièrement d'accord avec toi.

--
André Heinen
Mon e-mail, encodé ROT13: n qbg urvara ng rhebcrnayvax qbg pbz
La FAQ: http://www.cmla.ens-cachan.fr/Utilisateurs/dosreis/C++/FAQ/



Avatar
kanze
Alexandre wrote:
Je n'ai jamais utilisé de donnée membre de type référence
(je ne m'en vante pas, c'est comme ça). Les données membres
classiques de types pointeur ne sont me semble-t-il pas
transformables en références. Les contraintes sur une donnée
membre référence sont telles que les cas d'utilisations sont
certainement très spécifiques: la référence doit être
initialisée explicitement dans le constructeur, et ne
pourraêtre modifiée (l'affectation, pas l'objet référencé,
bien sûr). L'objet référencé doit donc exister avant la
classe et ne pourra être détruit qu'après la destruction de
la classe.


un cas (il me semble) classique : un membre flux (ostream, par
ex) qui est donc uniquement référencé dans la classe.

class X
{
std::ostream& FluxDeSortie;
public:
X(std::ostream& Flux):FluxDeSortie(Flux);
void Print(const std::string& s) {Flux<<s;}
};

X flux_console(std::cout);
flux_console.Print("sortie sur console");
std::ofstream UnFichier("essai.txt");
X flux_fichier(UnFichier);
flux_fichier.Print("sortie sur fichier");


Reste le problème que la classe ne supporte pas l'affectation.
Qui peut être parfois genant.

Aussi, l'utilisation du pointeur nul peut être utile pour faire
un flux sur rien.

(Ça ne veut pas dire que le cas ne se présente jamais. Seulement
qu'en tant que member, il y a des considérations supplémentaires
qui pèsent souvent pour le pointeur, par rapport au cas des
paramètres.)

--
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
Alexandre wrote:
Je pense que cette tègle ne souffre pas d'exceptions.


void
destroy( MaClasse& c )
{
if ( ! c.canDestroy() ) {
throw CannotDestroyError ;
}
delete &c ;
}

Je connais pas mal de programmeurs qui rechigneraient à la
ligne « delete &c ». Et qui préfèreraient passer un pointeur
dans ce cas-ci.


tout à fait, moi itou. En fait, si fondamentalement l'objet
EST un pointeur, pourquoi passer "artificiellement" une
référence ?


Mais ça veut dire quoi : fondamentalement l'objet est un
pointeur ? Ici, pour l'utilisateur, il s'agit toujours des
objets de type MaClasse.

par exemple, ceux qui utilisent C++ Builder savent que les
objets VCL ne peuvent être construits qu'avec new. Donc qu'on
ne manipule que des pointeurs. Donc passage d'un pointeur...


Tout à fait. Il y a des conventions existantes auxquelles on
adhère, même si elles violent nos conventions par ailleurs.
Déjà, par exemple, il y a une tradition de passer des streambuf
par pointeur, et des [io]stream par référence. Or que j'ai bien
des cas où je garantis que le streambuf* n'est pas nul (et ne
changera pas), et j'ai aussi des cas où j'ai été obligé de
passer le [io]stream par pointeur, parce qu'il pouvait être nul.

Il n'y a pas que la logique en jeu.

Et puis on peut passer un pointeur.. par référence... Exemple
: on code une fonction récursive sur un parcours d'arbre, un
passe une feuille (par son adresse) par référence (pour
pouvoir faire un new dessus par exemple...)


En fait, c'est une autre raison d'utiliser un pointeur. On ne
peut pas avoir une référence à une référence. Donc, un niveau
d'indirection au maximum. (Or que c'est bien connu, la solution
de tout problème, c'est d'introduire un niveau d'indirection
supplémentaire.)

--
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
Alexandre
Mais ça veut dire quoi : fondamentalement l'objet est un
pointeur ? Ici, pour l'utilisateur, il s'agit toujours des
objets de type MaClasse.


je voulais dire : quand tu ne peux manipuler que via un pointeur, pas par
une valeur (par ex les composants VCL, comme dit dans mon post précédent)

1 2 3