2015-03-04 6 views
5

Ich habe festgestellt, dass der Intel-Compiler keine Rückgabewertoptimierung für std :: array-Objekte generiert. Der folgende Code, der sich zufällig in der inneren Schleife meines Programms befindet, ist nicht so optimiert, wie er könnte.Muss die Rückgabewertoptimierung einen Kopierkonstruktor deklarieren

std::array<double, 45> f(const std::array<double, 45>& y) { 
    auto dy_dt = std::array<double, 45>(); 
    ... 

    return dy_dt; 
} 

Ich habe herausgefunden, dass dieses Verhalten kommt von der Tatsache, dass meine Standard-Bibliothek Implementierung eine Kopie Konstruktor für nicht explizit std :: Array definieren. Der folgende Code zeigt, dass:

class Test { 
public: 
    Test() = default; 
    Test(const Test& x); 
}; 

Test f() { 
    auto x = Test(); 

    return x; 
} 

Wenn Sie es kompilieren mit

icpc -c -std=c++11 -qopt-report=2 test.cpp -o test.o 

der Report-Datei zeigt

INLINE REPORT: (f(Test *)) [1] main.cpp(7,10) 

was beweist, dass der Compiler RVO erzeugt (die Signatur von f geändert wird Damit kann das neu erstellte Objekt auf dem Stapel der aufrufenden Site abgelegt werden. Aber wenn Sie die Zeile aus kommentieren, die Test(const Test& x); erklärt, die Report-Datei zeigt

INLINE REPORT: (f()) [1] main.cpp(7,10) 

was beweist, dass RVO nicht erzeugt wird.

In 12.8.31 des C++ 11-Standards, der RVO definiert, hat das Beispiel, das sie geben, einen Kopierkonstruktor. Also, ist das ein "Bug" des Intel-Compilers oder eine konforme Implementierung des Standards?

+0

@ Cyber ​​Nein, wenn RVO möglich wäre, würde es die Kopie elide. – juanchopanza

+0

Cyber: Nein, das ist die Rückgabewert-Optimierung, die hier involviert ist. Es hat nichts mit der Bewegungssemantik zu tun. – InsideLoop

+0

RVO benötigt keinen Kopierkonstruktor, aber Code, für den RVO gelten würde, benötigt einen gültigen Kopier- oder Verschiebekonstruktor, um verfügbar zu sein. – juanchopanza

Antwort

1

Dieses Programm verursacht ein undefiniertes Verhalten, ohne dass eine Diagnose erforderlich ist, weil die Regel für die Definition verletzt wurde.

Ein Kopierkonstruktor ist odr- bei der Rückgabe durch den Wert - even if copy elision takes place.

Eine Nicht-Inline-Funktion ist odr-used bedeutet, dass genau eine Definition der Funktion im Programm erscheinen muss. Sie haben jedoch keine angegeben, und Ihre Deklaration des Kopierkonstruktors unterdrückt die vom Compiler generierte Definition.

+0

Ich denke, es ist wahrscheinlich, weil nicht der gesamte Code angezeigt wird. Er hat auch keine Hauptleitung zur Verfügung gestellt. Hypothetisch könnte es eine andere Datei test2.cpp geben, nicht gezeigt oder erwähnt, die die Definition dieses Kopierkonstruktors hat. Oder es könnte in main.cpp sein. – thang

+0

@Matt: Ich verstehe deinen Standpunkt nicht. Wenn Sie keinen Kopierkonstruktor definieren, definiert der Standard einen für Sie. – InsideLoop

+0

@InsideLoop nein; Wenn Sie keinen Kopierkonstruktor * deklarieren, deklariert und definiert der Compiler einen für Sie. Auch, wie ethang hervorhebt, wäre es nützlich, wenn Sie ein gültiges Programm (oder einen Versuch zu einem) gepostet haben. Sie können keinen Optimierungsfehlerbericht basierend auf einem Programm, das nicht kompiliert wird, ablegen. –

Verwandte Themen