2013-03-15 14 views
7

Betrachten Sie den folgenden Code (LWS):g ++ vs Intel/Clang Argument übergeben Reihenfolge?

#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; 
} 

Sie haben es mehrmals laufen, weil manchmal, gibt es keinen sichtbaren Unterschied. Aber wenn es ein sichtbarer Unterschied zwischen dem Zeitpunkt der Auswertung von first und second ist, ist das Ergebnis die folgende unter g ++:

1363376239363175 
1363376239363174 

und die folgenden unter Intel und Klirren:

1363376267971435 
1363376267971436 

Es bedeutet, dass Unter g ++ wird das Argument second zuerst ausgewertet, und unter Intel und Clam wird das first Argument zuerst ausgewertet.

Welches ist nach dem C++ 11-Standard wahr?

+2

Ordentliche Art und Weise, die Bewertungsreihenfolge zu finden. – GManNickG

Antwort

14

Welches ist nach dem C++ 11-Standard wahr?

Beide sind zulässig. Um den Standard (§8.3.6) zu zitieren:

Die Reihenfolge der Auswertung von Funktionsargumenten ist nicht spezifiziert.

+0

Yup. Das hat mich in meiner Karriere schon ein paar Mal gebissen. Die Mehrdeutigkeit der Auswertung von Funktionsargumenten kann zu EXTREM subtilen Problemen führen. (Ich erinnere mich an eine Zeit, in der dieser Fehler jahrelang existierte, und ich konnte die Ursache nicht finden, und die einzige Abhilfe, die ich finden konnte, war OPTIONIERUNG FÜR DIESEN CPP. Autsch. – StilesCrisis

+0

Auch die Reihenfolge könnte von der Optimierung abhängen Flags verwendet und auf den Rest des Codes. –

+0

@StilesCrisis Ja, und selbst wenn Sie sich der Reihenfolge der undefinierten Argumentauswertung bewusst sind, müssen Sie daran denken, dass das Objekt, an dem eine Methode aufgerufen wird, nur ein weiteres Argument ist. Ist mir einmal passiert, weil ich gedacht habe: "Nun, um eine Methode durch' -> 'aufzurufen, muss sie erst die linke Seite auswerten, bevor man sich überhaupt mit den Methodenargumenten beschäftigt, oder?" *. –

0

Ich habe ein etwas einfacheres Beispiel, um das gleiche Problem zu veranschaulichen.

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