Makrodefinicja a postinkrementacja

Mam taki oto prosty kod:

#include 


using namespace std;


#define SQR(X) ((X)*(X))


int main()

{

	int nZmienna = 7;

	cout << SQR(nZmienna++) << endl;

	cout << nZmienna << endl << endl;


	system("pause");

	return 0;

}

i dlaczego pierwszy cout wypisuje mi 49? Przecież makro rozwijane jest do:

cout << (nZmienna++)*(nZmienna++);

czyli 7*8=56! !!

Drugi cout wypisuje poprawnie 9!

cout << SQR(++nZmienna) << endl;

da wynik 81, należy pamiętać że inkrementacja przyrostkowa owszem zwiększa wartość zmiennej ale zwraca starą wartość.

cout << (nZmienna++)*(nZmienna++);

oznacza:

cout << nZmienna*nZmienna; nZmienna+=2;

Nieprawda, wina leży po stronie języka i tego, że do typów prymitywnych stosują się trochę inne reguły niż w analogicznych metodach klas (tu akurat ze względu na oczekiwaną optymalizację). Wystarczy zbadać poniższy kod, aby dostrzec różnicę:

#include 


using namespace std;


class Integer {

private:

  int value;

public:

  Integer(int _value = 0)

    : value(_value)

  {

  }

  Integer(const Integer &a)

    : value(a.value)

  {

  }


  int get_value() const

  {

    return value;

  }


  const Integer operator++(int dummy)

  {

    Integer tmp(*this);


    cerr << ">> " << tmp.get_value() << "++"<< endl;;


    ++value;

    return tmp;

  }


  friend const Integer operator*(const Integer &a, const Integer &b)

  {

    cerr << ">> " << a.get_value() << " * " << b.get_value() << endl;;

    return a.value * b.value;

  }

};


#define SQR(X) ((X) * (X))


int main()

{

  Integer i(7);

  int j = 7;


  cout << SQR(i++).get_value() << endl; // ok 

  cout << SQR(j++) << endl; // warning: operation on ‘j’ may be undefined


  return 0;

}

A co ma jedno do drugiego?

Kolega pyta czemu mu nie wychodzi 81 (9*9).