2013-03-15 15 views
7

Rozważmy następujący kod (LWS):g ++ kontra Intel/Clang argument przekazujący zamówienie?

#include <iostream> 
#include <chrono> 

inline void test(
    const std::chrono::high_resolution_clock::time_point& first, 
    const std::chrono::high_resolution_clock::time_point& second) 
{ 
    std::cout << first.time_since_epoch().count() << std::endl; 
    std::cout << second.time_since_epoch().count() << std::endl; 
} 

int main(int argc, char* argv[]) 
{ 
    test(std::chrono::high_resolution_clock::now(), 
     std::chrono::high_resolution_clock::now()); 
    return 0; 
} 

trzeba go uruchomić kilka razy, ponieważ czasami nie ma widocznej różnicy. Ale kiedy jest widoczna różnica w czasie między oceną first i second, wynik jest następujący pod g ++:

1363376239363175 
1363376239363174 

i następujący pod Intel i brzękiem:

1363376267971435 
1363376267971436 

oznacza to, że w g ++ argument second jest oceniany jako pierwszy, a pod intel i clang najpierw oceniany jest argument .

Który z nich jest zgodny ze standardem C++ 11?

+2

Dokładny sposób na ustalenie kolejności oceny. – GManNickG

Odpowiedz

14

Który z nich jest zgodny ze standardem C++ 11?

Obie są dopuszczalne. Aby zacytować standard (§8.3.6):

Kolejność oceny argumentów funkcji jest nieokreślona.

+0

Yup. To mnie ugryzło kilka razy w mojej karierze. Niejednoznaczność oceny argumentów funkcji może prowadzić do bardzo subtelnych problemów. (Pamiętam, że kiedyś ten błąd istniał przez wiele lat i nie mogłem znaleźć przyczyny źródłowej, a jedyne obejście, jakie mogłem znaleźć, to WYŁĄCZENIE OPTYMALIZACJI DLA TEGO CPP. Ouch.) – StilesCrisis

+0

Kolejność może zależeć od optymalizacji używane flagi i reszta kodu. –

+0

@StilesCrisis Tak, i nawet jeśli jesteś świadomy niezdefiniowanej kolejności oceny argumentów, musisz pamiętać, że obiekt, do którego dana metoda jest wywoływana, jest po prostu kolejnym argumentem. Zdarzyło mi się kiedyś, ponieważ pomyślałem * "cóż, aby wywołać metodę przez' -> ", musi najpierw ocenić lewą stronę, zanim jeszcze zacznie patrzeć na argumenty metody, czyż nie?" *. –

0

Mam nieco prostszy przykład ilustrujący ten sam problem.

bash$ cat test.cpp 
#include <iostream> 
using namespace std; 
int x = 0; 
int foo() 
{ 
    cout << "foo" << endl; 
    return x++; 
} 
int bar() 
{ 
    cout << "bar" << endl; 
    return x++; 
} 
void test_it(int a, int b) 
{ 
    cout << "a = " << a << endl 
     << "b = " << b << endl; 

} 
int main(int argc, const char *argv[]) 
{ 
    test_it(foo(),bar()); 
    return 0; 
} 

bash$ clang++ test.cpp && ./a.out 
foo 
bar 
a = 0 
b = 1 
bash$ g++ test.cpp && ./a.out 
bar 
foo 
a = 1 
b = 0 
Powiązane problemy