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

Ordre des evaluations d'arguments

4 réponses
Avatar
Robert
Bonjour

Je suis tombe sur un comportement "bizarre":

std::cout << funca() << funcb() << std::endl;

L'appel a funcb est execute avant l'appel a funca

Est-ce normal?

Si c'etait le cas suivant:
func(funca(), funcb())
la, ok les arguments peuvent etre evalues dans n'importe
quel ordre mais dans le cas de l'operateur <<, je pensais
que le code pouvait aussi s'ecrire

std::cout.operator<<(funca()).operator<<(funcb()).operator<<(std::endl);

Et donc, ce n'est pas un appel mais plusieurs appels successif a <<
et donc les arguments devraient etre evalue dans l'ordre.

Quelqu'un peut-il si c'est le compilo qui a tort ou si c'est
moi qui est completement off.

Robert

4 réponses

Avatar
Horst Kraemer
On Fri, 18 Jun 2004 17:41:06 +0200, Robert
wrote:

Bonjour

Je suis tombe sur un comportement "bizarre":

std::cout << funca() << funcb() << std::endl;

L'appel a funcb est execute avant l'appel a funca

Est-ce normal?

Si c'etait le cas suivant:
func(funca(), funcb())
la, ok les arguments peuvent etre evalues dans n'importe
quel ordre mais dans le cas de l'operateur <<, je pensais
que le code pouvait aussi s'ecrire

std::cout.operator<<(funca()).operator<<(funcb()).operator<<(std::endl);

Et donc, ce n'est pas un appel mais plusieurs appels successif a <<
et donc les arguments devraient etre evalue dans l'ordre.


Non. Dans une expression comme

x.f(func(a)).f(func(b))

le compilateur a le droit d'évaluer func(b) avant func(a).

Tous mes compilateurs (entre eux Borland bcc32 et gcc) donnent le
résultat

1 2
2 1

avec le programme suivant ce qui prouvent que le premier appel de 'f'
est effectué avec le résultat de la deuxième évaluation de 'func' et
le deuxième appel de 'f' avec le résultat de la première évaluation de
'func'

#include <cstdio>

struct X
{
X() : count(0) {}
struct X& f(int i) { std::printf("%d %dn",++count,i);
return this;
}
int count;
};

int func()
{
static int i=0;
return ++i;
}

int main()
{
X x;
x.f(func()).f(func());
return 0;
}


--
Horst

Avatar
Fabien LE LEZ
On Fri, 18 Jun 2004 17:41:06 +0200, Robert
:

std::cout << funca() << funcb() << std::endl;

L'appel a funcb est execute avant l'appel a funca


A priori, si funcb ne dépend pas de la valeur de retour de funca, il
n'y a aucun empêchement.

Note que si ton code se base sur le fait que f() est appelé avant g(),
il est très chaudement recommandé de l'expliciter, ne serait-ce que
pour celui qui lira le code :

MonType a= f();
MonType b= g();
cout << a << b << endl;



--
schtroumpf schtroumpf

Avatar
Franck Branjonneau
Robert écrivait:

std::cout << funca() << funcb() << std::endl;

std::cout.operator<<(funca()).operator<<(funcb()).operator<<(std::endl);


Non, plutôt

std::operator<<(std::operator<<(std::operator<<(std::cout, funca()), funcb()), std::endl);
--
Franck Branjonneau

Avatar
Robert
Non. Dans une expression comme

x.f(func(a)).f(func(b))

le compilateur a le droit d'évaluer func(b) avant func(a).


Merci de l'info, je pensais que le . imposait l'evaluation
complete de ce qui precede avant d'executer ce qui suit.
Donc finalement que ce soit

std::cout.operator<<(...)

ou

operator<<(std::cout, ...)

Ca ne change rien, le compilateur peut faire comme il veut dans
l'ordre d'evaluation des divers arguments.

Merci a tous pour vos explications

Robert