OVH Cloud OVH Cloud

pointeur sur objet muet

8 réponses
Avatar
Yann Renard
Bonjour à tous,

une petite question rapide car je sais qu'il y a des gourous de la norme
ici ;)

j'ai une fonction qui attend un pointeur en paramètre. l'objet que je
veux passer est temporaire et ne sera pas utilisé par la suite ; afin de
ne pas rajouter trop de lignes à mon programme, j'aimerais le passer de
manière muette, sans le nommer.

--> ce qu'il faudrait faire :
A a(p1, p2, ...);
f(&a);

--> ce sur quoi j'ai un doute :
f(&::A(p1, p1, ...));

Visual me permet de faire ca, mais je ne suis pas convaincu que ce soit
correcte d'un point de vue norme. Qu'en pensez vous ?

Merci d'avance et a+
--
Yann Renard - To send me an email, remove no-spam sectionS :)

8 réponses

Avatar
Fabien LE LEZ
On Mon, 19 Dec 2005 14:57:25 +0100, Yann Renard
:

--> ce qu'il faudrait faire :
A a(p1, p2, ...);
f(&a);

--> ce sur quoi j'ai un doute :
f(&::A(p1, p1, ...));


Qu'est-ce que le "::" vient faire ici, alors qu'il n'est pas présent
plus haut ?

Soit le code ci-dessous :

struct A
{
A (int, int);
};

void f (A*);

int main()
{
f (&A(1,2));
}

L'intuition fait tiquer, mais j'aurais pensé que ce code était
correct. Ben non, Comeau râle :

error: expression must be an lvalue or a function designator
f (&A(1,2));
^

Avatar
Yann Renard
Bonjour Fabien,

Fabien LE LEZ wrote:
Qu'est-ce que le "::" vient faire ici, alors qu'il n'est pas présent
plus haut ?


J'ai été un peu vite, mais on s'est compris ;)

Soit le code ci-dessous :

struct A
{
A (int, int);
};

void f (A*);

int main()
{
f (&A(1,2));
}

L'intuition fait tiquer, mais j'aurais pensé que ce code était
correct. Ben non, Comeau râle :

error: expression must be an lvalue or a function designator
f (&A(1,2));
^


Merci pour cette réponse, qui confirme ce que je pensais ;)

A+
Yann
--
Yann Renard - To send me an email, remove no-spam sectionS :)

Avatar
Fabien LE LEZ
On Mon, 19 Dec 2005 15:17:54 +0100, Yann Renard :

Merci pour cette réponse, qui confirme ce que je pensais ;)


Si tu n'as pas Comeau, tu peux tester du code ici :
<http://www.comeaucomputing.com/tryitout/>.

Accessoirement, une version récente de g++, en mode le plus strict,
devrait faire l'affaire.

Avatar
Jean-Marc Bourguet
Fabien LE LEZ writes:

Soit le code ci-dessous :

struct A
{
A (int, int);
};

void f (A*);

int main()
{
f (&A(1,2));
}

L'intuition fait tiquer, mais j'aurais pensé que ce code était
correct. Ben non, Comeau râle :

error: expression must be an lvalue or a function designator
f (&A(1,2));
^


A noter que le code n'est pas non plus valide avec f(A const*) a la
place de f(A*).

A comparer avec passer un temporaire a f(A const&) qui est permis
tandis qu'a f(A&) ce ne l'est pas.

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
Yann Renard
Fabien LE LEZ wrote:
On Mon, 19 Dec 2005 15:17:54 +0100, Yann Renard :


Merci pour cette réponse, qui confirme ce que je pensais ;)



Si tu n'as pas Comeau, tu peux tester du code ici :
<http://www.comeaucomputing.com/tryitout/>.

Accessoirement, une version récente de g++, en mode le plus strict,
devrait faire l'affaire.


Superbe, merci beaucoup !

Yann
--
Yann Renard - To send me an email, remove no-spam sectionS :)


Avatar
Pierre THIERRY
Le Mon, 19 Dec 2005 14:57:25 +0100, Yann Renard a écrit :
--> ce qu'il faudrait faire :
A a(p1, p2, ...);
f(&a);

--> ce sur quoi j'ai un doute :
f(&::A(p1, p1, ...));


Ce qui marche :

f(boost::scoped_ptr<A>(new A(p1, p2, ...)).get());

Ça ne simplifie pas vraiment l'écriture, mais si tu as besoin de passer
un objet non nommé, ça fonctionne.

Brièvement,
Nowhere man
--

OpenPGP 0xD9D50D8A

Avatar
Yann Renard
Pierre THIERRY wrote:

--> ce qu'il faudrait faire :
A a(p1, p2, ...);
f(&a);

--> ce sur quoi j'ai un doute :
f(&::A(p1, p1, ...));



Ce qui marche :

f(boost::scoped_ptr<A>(new A(p1, p2, ...)).get());

Ça ne simplifie pas vraiment l'écriture, mais si tu as besoin de passer
un objet non nommé, ça fonctionne.

Brièvement,
Nowhere man


Mais ca force à faire une allocation dynamique et à inégrer boost dans
un projet qui ne l'utilise pas...

Je préfère la methode avec plus de lignes ;)

Merci quand même pour la réponse...
A+

Yann
--
Yann Renard - To send me an email, remove no-spam sectionS :)


Avatar
kanze
Pierre THIERRY wrote:
--> ce qu'il faudrait faire :
A a(p1, p2, ...);
f(&a);

--> ce sur quoi j'ai un doute :
f(&::A(p1, p1, ...));


Ce qui marche :

f(boost::scoped_ptr<A>(new A(p1, p2, ...)).get());


Mais il ment pas mal -- scoped_ptr signifie une propriété partagée,
qui
n'est pas le cas ici.

Si tu veux rester standard, tu peux faire exactement la même chose
avec
auto_ptr. Si tu utilises des extensions, un simple new suffit, et le
glaneur de cellules s'occupe de la reste. (Et comme extension, le
glaneur de cellules est à la fois plus simple à installer et à
utiliser,
et plus utile que Boost. Ce qui n'est pas peu dire, parce qu'il y a des
choses vraiment utiles dans Boost.)

Ça ne simplifie pas vraiment l'écriture, mais si tu as besoin de
passer un objet non nommé, ça fonctionne.


Non seulement c'est lourd à l'écriture, mais ça utilise de la
mémoire
dynamique, ce qui peut aussi représenter une lourdeur.

La règle de la norme est simple : l'opérateur unaire & a besoin d'un
« lvalue ». Ici, formellement, on a un « function style cast »,
bien que
moi, j'ai du mal à concevoir A( p1, p2, ... ) comme une conversion).
Un
« function style cast » n'est pas un lvalue. C'est donc illégal.

AMHA, la solution la plus claire et la plus lisible reste la variable
explicite. N'importe qui qui connaît un peu du C++ sait immédiatement
exactement ce que ça fait. Sinon... il s'agit d'un type « classe ».
Donc, même un lvalue est un objet. Et un objet a certains
caractèristiques d'un lvalue, même quand il n'en est pas un :
surtout,
il a une adresse, et on peut en appeler des fonctions membres. On en
peut aussi surcharger l'opérateur &, et alors, l'application de & est
un
appel de fonction membre, ce qui peut se faire sur un rvalue. Si tu as
accès à A, tu peux lui en fournir un surcharge :

A* A::operator&() { return this ; }
A const* A::operator&() const { return this ; }

Sinon, tu peux en dériver, et fournir l'opérateur ci-dessus dans la
classe dérivée.

Mais comme j'ai dit, AMHA, ça relève de l'obfuscation plus que de la
bonne programmation. Déjà une fonction avec un nom bien parlant
signalera mieux au lecteur qu'il se passe quelque chose de spécial.
Mais
je crois qu'en général, la variable nommée est la plus claire et la
plus explicite.

--
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