OVH Cloud OVH Cloud

[Debutan C++] Retour pointeur

51 réponses
Avatar
PtitMat
Bonjour,

Je voudrais ecrire une fonction qui me retourne un pointeur vers une
variable.
Est-ce possible?
Je vous remercie pour votre aide

Mat.

10 réponses

1 2 3 4 5
Avatar
Christophe Lephay
PtitMat wrote:
Je voudrais ecrire une fonction qui me retourne un pointeur vers une
variable.
Est-ce possible?
Je vous remercie pour votre aide


C'est possible si la variable n'est pas locale :

// la variable existe en dehors de la fonction
int * fonction( int & variable )
{
return &variable;
}

Si c'est ta fonction qui la crée, sa durée de vie doit dépasser le stade de
la fonction et la variable ne peut donc plus être auto :

int * fonction()
{
int mal;
int * bon = new int;

// return &mal; // comme son nom l'indique
return bon; // c'est le code appelant qui devient responsable de la durée de
vie de la variable
}

Du point de vue du design, c'est souvent le signe d'une mauvaise conception
que de melanger variables (ou objets, dirons-nous) et pointeurs car celà
indique souvent qu'on gère pele-mêle différents niveaux d'abstractions.

Chris

Avatar
Falk Tannhäuser
PtitMat wrote:
Je voudrais ecrire une fonction qui me retourne un pointeur vers une
variable.
Est-ce possible?


Oui, tant qu'il ne s'agit pas d'une variable locale automatique.
Je ne sais pas si cela répond à ta question - qu'est-ce que tu
veux faire exactement ?

Falk

Avatar
Fabien LE LEZ
On Wed, 17 Nov 2004 18:58:23 +0000, PtitMat :

Est-ce possible?


C'est possible (presque tout est possible en C++ ;-) ), mais pas
forcément une bonne idée.


--
;-)

Avatar
PtitMat
Christophe Lephay wrote:

PtitMat wrote:

Je voudrais ecrire une fonction qui me retourne un pointeur vers une
variable.
Est-ce possible?
Je vous remercie pour votre aide



C'est possible si la variable n'est pas locale :

// la variable existe en dehors de la fonction
int * fonction( int & variable )
{
return &variable;
}

Si c'est ta fonction qui la crée, sa durée de vie doit dépasser le stade de
la fonction et la variable ne peut donc plus être auto :

int * fonction()
{
int mal;
int * bon = new int;

// return &mal; // comme son nom l'indique
return bon; // c'est le code appelant qui devient responsable de la durée de
vie de la variable
}

Du point de vue du design, c'est souvent le signe d'une mauvaise conception
que de melanger variables (ou objets, dirons-nous) et pointeurs car celà
indique souvent qu'on gère pele-mêle différents niveaux d'abstractions.

Chris


Merci


Une autre question plus de syntax :
Voici ma fonction écrite selon vos conseils :

int * Ccpu::dToR (int dx)
{
if (dx == 0)
{
return pR0;
}
if (dx == 1)
{
return pR1;
}
if (dx == 2)
{
return pR2;
}
if (dx == 3)
{
return pR3;
}
}

J'ai un warning a la compilation me disant que je ne retourn pas dans
tous les cas un element correct ce qui est vrai si dx vaut 4 par exemple
mais ce cas n'arivera pas : il y aura un control en amont avant
d'appeler la fonction.

Ma question est donc la suivant serait-il mieux d'enchainer les if dans
des else avec quelque chose du style

int * Ccpu::dToR (int dx)
{
if (dx == 0)
{
return pR0;
}
else
{
if (dx == 1)
{
return pR1;
}
else
{
if (dx == 2)
{
return pR2;
}
else
{
if (dx == 3)
{
return pR3;
}
}
}
}
}


Avatar
Fabien LE LEZ
On Wed, 17 Nov 2004 19:23:16 +0000, PtitMat :

J'ai un warning a la compilation me disant que je ne

retourn


Efforce-toi d'écrire toutes les lettres. Usenet != SMS.

pas dans
tous les cas un element correct ce qui est vrai si dx vaut 4 par exemple

mais ce cas n'arivera pas


Tu n'as aucun moyen d'en être sûr. Le mieux est de lancer une
exception en cas de paramètre incorrect.

Ma question est donc la suivant serait-il mieux d'enchainer les if dans
des else avec quelque chose du style


C'est illisible, donc forcément moins bien.

Mais bon, pourquoi faire compliqué ? Un switch conviendrait tout aussi
bien.
De plus, si ta fonction renvoie forcément un pointeur valide, autant
renvoyer une référence à la place :

int& Ccpu::dToR (int dx)
{
switch (dx)
{
case 0: return *pR0;
case 1: return *pR1;
case 2: return *pR2;
case 3: return *pR3;
default: throw std::domain_error
("Ccpu::dToR : paramètre invalide");
}
}

Mais bon, de toutes façons cette fonction devrait AMHA être inutile.
Tu as plusieurs pointeurs ayant presque le même nom ; un tableau
( std::vector<int*> ) conviendrait a priori bien mieux.

D'autre part, choisis des noms plus explicites !
"dToR" n'est pas un bon nom, car il n'indique pas au premier coup
d'oeil ce que fait la fonction. De même pour dx et pR0.


--
;-)

Avatar
Christophe Lephay
PtitMat wrote:
Une autre question plus de syntax :
Voici ma fonction écrite selon vos conseils :

int * Ccpu::dToR (int dx)
{
if (dx == 0)
{
return pR0;
}
if (dx == 1)
{
return pR1;
}
if (dx == 2)
{
return pR2;
}
if (dx == 3)
{
return pR3;
}
}

J'ai un warning a la compilation me disant que je ne retourn pas dans
tous les cas un element correct ce qui est vrai si dx vaut 4 par
exemple mais ce cas n'arivera pas : il y aura un control en amont
avant d'appeler la fonction.


Tu peux faire un switch...case et/ou :

int Ccou::dToR( int dx )
{
xxx * Pr;

switch( dx )
{
case 0: pR = pR0; break;
case 1: pR = pR1; break;
...
default: throw( "erreur" );
}

return pR;
}

Par ailleurs, il est bien possible que tu puisses mettre en oeuvre du
polymorphisme pour remplacer ces tests, mais c'est dur d'affirmer quoique ce
soit sans connaitre plus précisément ton problème :

- C'est quoi tes pR0...pRn ?
- Est-ce que ton objet peut à un moment donné avoir tous ces pRn
simultanément valides ? Ou un seul peut-il l'etre à la fois (auquel cas le
polymorphisme est plus approprié) ?

Chris

Avatar
PtitMat
Christophe Lephay wrote:

PtitMat wrote:

Une autre question plus de syntax :
Voici ma fonction écrite selon vos conseils :

int * Ccpu::dToR (int dx)
{
if (dx == 0)
{
return pR0;
}
if (dx == 1)
{
return pR1;
}
if (dx == 2)
{
return pR2;
}
if (dx == 3)
{
return pR3;
}
}

J'ai un warning a la compilation me disant que je ne retourn pas dans
tous les cas un element correct ce qui est vrai si dx vaut 4 par
exemple mais ce cas n'arivera pas : il y aura un control en amont
avant d'appeler la fonction.



Tu peux faire un switch...case et/ou :

int Ccou::dToR( int dx )
{
xxx * Pr;

switch( dx )
{
case 0: pR = pR0; break;
case 1: pR = pR1; break;
...
default: throw( "erreur" );
}

return pR;
}

Par ailleurs, il est bien possible que tu puisses mettre en oeuvre du
polymorphisme pour remplacer ces tests, mais c'est dur d'affirmer quoique ce
soit sans connaitre plus précisément ton problème :

- C'est quoi tes pR0...pRn ?
- Est-ce que ton objet peut à un moment donné avoir tous ces pRn
simultanément valides ? Ou un seul peut-il l'etre à la fois (auquel cas le
polymorphisme est plus approprié) ?

Chris


Ce qui se passe :

J'ai un ordinateur composé d'une rom et d'un cpu
La rom est initialisé au début avec les instructions sous la forme d'un
tableau d'entier.
Une insrtuction a 3 chifres (341 ar exemple)
Le chifre numéro 1 appelé d1 (digit 1) indique le type d'opération
assembleur
Les chiffres 2 et 3 (d2 et d3) sont les opérandes.
Beaucoup de fonctions ont des operandes qui sont des numéros de
registres du CPU
Exemple move_value (value, Registre)
Ajoute(ValueRx, ValueRy)
Mes registres sont appelés R0 a R3

Ma fonction move_value (value, Registre)
appelle la fonction dToR pour convertir le digit qui lui est passé en
paramètre en pointeur vers le registre de manière a écrire la valeur dan
le bon registre.

J'ai pensé intelligent avec mon niveau de C++ de faire comme j'ai fait
mais 'est vrai qu'un swtch est plus propre.
De plus une gestion de l'erreur a se niveaux est sécuritaire, mais je ne
conaiisait pas cette commande :
default: throw( "erreur" );

Merci

Matthieu


Avatar
Jean-Marc Bourguet
PtitMat writes:

if (dx == 0)
{
return pR0;
}
if (dx == 1)
{
return pR1;
}
if (dx == 2)
{
return pR2;
}
if (dx == 3)
{
return pR3;
}


switch

pour des conditions plus complexes:

if () {
...
} else if {
...
} else if {
...
} else {
...
}

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org

Avatar
Fabien LE LEZ
On Wed, 17 Nov 2004 20:10:50 +0000, PtitMat :

conaiisait pas cette commande :
default: throw( "erreur" );


Jette-toi sur ton bouquin de C++, section "exceptions"...


--
;-)

Avatar
Christophe Lephay
PtitMat wrote:
Ce qui se passe :
J'ai un ordinateur composé d'une rom et d'un cpu
La rom est initialisé au début avec les instructions sous la forme
d'un tableau d'entier.
Une insrtuction a 3 chifres (341 ar exemple)
Le chifre numéro 1 appelé d1 (digit 1) indique le type d'opération
assembleur
Les chiffres 2 et 3 (d2 et d3) sont les opérandes.
Beaucoup de fonctions ont des operandes qui sont des numéros de
registres du CPU
Exemple move_value (value, Registre)
Ajoute(ValueRx, ValueRy)
Mes registres sont appelés R0 a R3

Ma fonction move_value (value, Registre)
appelle la fonction dToR pour convertir le digit qui lui est passé en
paramètre en pointeur vers le registre de manière a écrire la valeur
dan le bon registre.

J'ai pensé intelligent avec mon niveau de C++ de faire comme j'ai fait
mais 'est vrai qu'un swtch est plus propre.
De plus une gestion de l'erreur a se niveaux est sécuritaire, mais je
ne conaiisait pas cette commande :
default: throw( "erreur" );


Le plus idiomatique serait de créer deux hiérarchies : une pour les
instructions, une autre pour les opérandes, puis une factory ("usine"
littéralement") qui te renverrait un pointeur sur un objet dérivé
instruction qui aurait lui-même extrait les opérandes de manière approprié.
Si tu débutes en C++, celà représente pas mal de choses à apprendre d'un
coup, mais tu bénéficierais de tous les avantages de la POO (en
l'occurrence, tu pourrais par la suite créer de nouvelles instructions sans
jamais avoir à changer le code qui aurait déjà été écrit, le rendant ainsi
facilement adaptable à d'autres CPUs).

En l'occurrence, la manière idiomatique de coder celà se ferait sans aucun
switch (une factory est généralement basée sur un tableau, éventuellement
associatif, de pointeurs de fonctions chargées chacune de construire des
objets d'un type spécifique). J'hésite à en dire plus à ce stade vu que tu
sembles débuter en C++. Si tu veux plus de détails, demande le en réponse à
ce post.

Chris

1 2 3 4 5