Czym jest podwójna ocena i dlaczego należy jej unikać?

Czym jest podwójna ocena i dlaczego należy jej unikać?

Wyobraź sobie, że napisałeś to:

#define Max(a,b) (a < b ? b : a)

int x(){ turnLeft();   return 0; }
int y(){ turnRight();  return 1; }

potem nazwał to tak:

auto var = Max(x(), y());

Czy wiesz, że turnRight() zostanie wykonany dwukrotnie? To makro, Max rozwinie się do:

auto var = (x() < y() ? y() : x());

Po ocenie warunku x() < y() , program następnie pobiera wymaganą gałąź między y() : x() :w naszym przypadku true , który wywołuje y() po raz drugi raz . Zobacz Na żywo w Coliru .

Mówiąc najprościej, przekazywanie wyrażenia jako argumentu do makra podobnego do funkcji, Max potencjalnie oceni to wyrażenie dwukrotnie, ponieważ wyrażenie będzie powtarzane w każdym przypadku, gdy parametr makra, którego przyjmie, zostanie użyty w definicji makra. Pamiętaj, makra są obsługiwane przez preprocesor .

Podsumowując, nie używaj makr do definiowania funkcji (w tym przypadku właściwie wyrażenia) tylko dlatego, że chcesz, aby była ogólna , podczas gdy można to skutecznie zrobić za pomocą szablonów funkcyjnych

PS:C++ ma std::max funkcja szablonu.


a i b występują dwa razy w definicji makra. Więc jeśli użyjesz go z argumentami, które mają efekty uboczne, efekty uboczne są wykonywane dwa razy.

max(++i, 4);

zwróci 6, jeśli i = 4 przed rozmową. Ponieważ nie jest to oczekiwane zachowanie, powinieneś preferować funkcje wbudowane, aby zastąpić takie makra, jak max .


Rozważ następujące wyrażenie:

 x = max(Foo(), Bar());

Gdzie Foo i Bar są takie:

int Foo()
{
    // do some complicated code that takes a long time
    return result;
}

int Bar()
{
   global_var++;
   return global_var;
}

Następnie w oryginalnym max wyrażenie jest rozwinięte jak:

 Foo() > Bar() ? Foo() : Bar();

W obu przypadkach Foo lub Bar zostaną wykonane dwukrotnie. W ten sposób trwa to dłużej niż to konieczne lub zmienia stan programu więcej niż oczekiwana liczba razy. W moim prostym Bar na przykład, nie zwraca konsekwentnie tej samej wartości.