2015-06-28 9 views
5

Ich habe verschiedene Ergebnisse mit Auto und Vector beim Summieren von zwei Vektoren.Falsche Ergebnisse mit Auto mit Eigen

Mein Code:

#include "stdafx.h" 
#include <iostream> 
#include "D:\externals\eigen_3_1_2\include\Eigen\Geometry" 

typedef Eigen::Matrix<double, 3, 1>  Vector3; 

void foo(const Vector3& Ha, volatile int j) 
{ 
    const auto resAuto = Ha + Vector3(0.,0.,j * 2.567); 
    const Vector3 resVector3 = Ha + Vector3(0.,0.,j * 2.567); 

    std::cout << "resAuto = " << resAuto <<std::endl; 
    std::cout << "resVector3 = " << resVector3 <<std::endl; 
} 

int main(int argc, _TCHAR* argv[]) 
{ 
    Vector3 Ha(-24.9536,-29.3876,65.801); 
    Vector3 z(0.,0.,2.567); 

    int j = 7; 

    foo(Ha,j); 
    return 0; 
} 

Die Ergebnisse:

resAuto = -24,9536, -29.3876,65.801

resVector3 = -24,9536, -29.3876,83.77

Press jeder Schlüssel, um fortzufahren. . .

Ich verstehe, dass Eigen interne Optimierung, die unterschiedliche Ergebnisse erzeugt. Aber es sieht wie ein Fehler in Eigen und C++ 11 aus.

+1

Wenn es klingt wie "ein Fehler in Eigen und C++ 11", ist es wahrscheinlich nicht. Lesen Sie die Dokumentation erneut sorgfältig und achten Sie dabei sorgfältig auf Ausdrucksvorlagen. –

+0

Es funktioniert erfolgreich für mich mit eigen 3.2.2. – user2658323

+0

Expression-Templates und andere Klassen, die Proxy-Typen zurückgeben (Vektor :: operator [] (size_t)), können bei Verwendung mit auto überraschend sein. Anstatt die Summe Ihrer Vektoren zu erhalten, erhalten Sie einen Typ, der den Ausdruck der Summe Ihrer beiden Vektoren speichert. Dies ist eine Vorlagenoptimierung, die oft für Live-Matrizen großer Objekte verwendet wird. In anderen Nachrichten gab es einen Vorschlag für "operator auto", der es dem Autor der Eigenen Klasse ermöglicht hätte, in Ihrem Fall ein tatsächliches Vector3 zurückzugeben. Ich kenne gcc und ich denke, Clang haben es reingeschmuggelt. Vielleicht hacken Sie Ihren eigenen "Operator Auto" und sehen Sie. – emsr

Antwort

2

Das Schlüsselwort auto teilt dem Compiler mit, das beste Objekt basierend auf der rechten Seite des = "zu erraten". Sie können die Ergebnisse überprüfen, indem

std::cout << typeid(resAuto).name() <<std::endl; 
std::cout << typeid(resVector3).name() <<std::endl; 

zu foo Hinzufügen (nicht vergessen <typeinfo> enthalten).

In diesem Fall wird nach dem Erstellen des temporären Vector3 die operator+-Methode aufgerufen, die ein Objekt CwiseBinaryOp erstellt. Dieses Objekt ist Teil von Eigenen lazy evaluation (kann Leistung erhöhen). Wenn Sie gerne Auswertung (und damit Typbestimmung) zwingen wollen, könnten Sie

const auto resAuto = (Ha + Vector3(0.,0.,j * 2.567)).eval(); 

statt Ihrer Linie in foo verwenden.

Ein paar Randnotizen:

  • Vector3 ist identisch mit der Vector3d Klasse definiert in Eigen
  • Sie #include <Eigen/Core> statt #include <Eigen/Geometry> können die meisten der Eigen-Header enthalten, sowie bestimmte Dinge dort festgelegt, dass sollte sein.