2017-09-05 12 views
2

Ist es möglich, einen Zeiger auf ein Eigen :: Map-Objekt zu definieren? Der ursprüngliche Code ist ziemlich komplex, aber hier ist das, was ich (Pseudocode)C++ Eigen-Zeiger auf ein Eigen :: Map <Eigen :: VectorXd> -Objekt

void testfunction1(... XPtr){ 
    // XPtr is a pointer 
    // create a vector, map it to a Map object and make XPtr point to the latter 

    VectorXd Xnew(9); 
    Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90; 
    Map<VectorXd> XnewMap(Xnew.data(), 9); 

    // make XPtr point to XnewMap so that Xnew data can be 
    // accessed outside testfunction1() 
    // ... how? I suspect this to involve some dynamic memory allocation 
}; 

void testfunction2(bool yes){ 
    // main function 

    VectorXd XR(9); 
    XR << 1, 2, 3, 4, 5, 6, 7, 8, 9; 
    const Map<VectorXd> X(XR.data(), 9); // yes the mapped version is needed 

    // create a pointer to X, say XPtr 
    // ... how? 

    if(yes){ // make XPtr point to XnewMap which is defined in testfunction1() 
    testfunction1(XPtr); 
    }; 

    //... some computations 

    // make XPtr point again to X 
    // ... how? 

}; 

Antwort

0

Zunächst einmal keine Notwendigkeit zu erreichen versuchen Zeiger hier zu verwenden, da Karte bereits im Wesentlichen ein Zeiger ist, so wäre es einfacher, so Update das Map-Objekt mit placement new. Nichtsdestoweniger würde Ihr derzeitiges Design eine Zuweisung innerhalb der Testfunktion1 und eine Freigabe innerhalb der Testfunktion2 erfordern, falls es zugewiesen wurde, was nicht wirklich sicher ist. Also besser ein funktionelles Design adoptieren durch „einige Berechnungen“ innerhalb einer Funktion (oder eine benannte Lambda) setzen, machen testfunction1 Rückkehr nach Wert:

VectorXd testFunction1() { return Xnew; } 

void testfunction2(bool yes){ 
    VectorXd XR(9); 
    XR << 1, 2, 3, 4, 5, 6, 7, 8, 9; 
    const Map<VectorXd> X(XR.data(), 9); 

    auto func = [&] (Eigen::Ref<VectorXd> X) { 
    /* some computation */ 
    } 

    if(yes) func(testfunction1()); 
    else func(X); 
}; 

Wenn Sie wirklich Ihre aktuelle Logik behalten möchten, dann ist hier eine Selbst -contained Beispiel mit Platzierung neuer:

#include <iostream> 
#include <Eigen/Dense> 
using namespace Eigen; 
using namespace std; 

void testfunction1(Map<VectorXd> &XMap){ 
    double * Xnew = new double[9]; 
    ::new (&XMap) Map<VectorXd>(Xnew,9); 
    XMap << 10, 20, 30, 40, 50, 60, 70, 80, 90; 
}; 

int main() 
{ 
    bool yes = true; 

    VectorXd XR(9); 
    XR << 1, 2, 3, 4, 5, 6, 7, 8, 9; 
    Map<VectorXd> X(XR.data(), 9); 

    if(yes) testfunction1(X); 

    // use X ... 
    cout << X.transpose() << endl; 

    // restore X and free memory allocated in testfunction1 
    if(yes){ 
    delete[] X.data(); 
    ::new (&X) Map<VectorXd>(XR.data(),9); 
    } 

    cout << X.transpose() << endl; 
} 

was ziemlich schlecht ist, weil es entweichen kann, wenn eine Ausnahme ausgelöst wird, wenn X verwendet, könnte Sie durch manuelle Speicherverwaltung umgehen testFunction1 bitten, eine VectorXd (oder irgendetwas zurückzugeben, die Speicher umgehen Allokation/Deallokation alleine) und die Platzierung neu in der Hauptfunktion vornehmen n:

#include <iostream> 
#include <Eigen/Dense> 
using namespace Eigen; 
using namespace std; 

VectorXd testfunction1(){ 
    VectorXd Xnew(9); 
    Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90; 
    return Xnew; 
}; 

int main() 
{ 
    bool yes = true; 

    VectorXd XR(9); 
    XR << 1, 2, 3, 4, 5, 6, 7, 8, 9; 
    Map<VectorXd> X(XR.data(), 9); 

    { 
    VectorXd X2; 
    if(yes) { 
     X2 = testfunction1(); // shallow copy thanks to move semantic 
     ::new (&X) Map<VectorXd>(X2.data(),9); 
    } 

    // use X ... 
    cout << X.transpose() << endl; 

    // restore X 
    ::new (&X) Map<VectorXd>(XR.data(),9); 
    } 

    cout << X.transpose() << endl; 
} 

Schließlich, wenn der Gehalt an X sollte nur gelesen wird, dann Map<const VectorXd> verwenden und nicht const Map<VectorXd> als in Ihrer ersten Frage.

+0

Danke für Ihre Antwort. Dies ist, was mein aktueller Code tut, aber es macht es schwierig zu lesen, da die if else-Anweisung andere Funktionen erfordert, aber ich werde Ihre Antwort akzeptieren, da sie für andere nützlich sein kann. Ich frage mich jedoch immer noch, wie man einen Zeiger auf Karte <...> – itQ

+0

deklarieren kann Nichts schwierig, deklarieren Sie einfach 'typedef const MapVectorXd ConstMapVectorXd;' und verwenden Sie dann 'ConstMapVectorXd *', aber Sie müssen mit komplexen dynamischen Speicherzuweisung für die beiden referenzierten Daten beschäftigen durch die neue Map und das Map-Objekt selbst, das immer anfällig für Fehler und Speicherleck ist. Wenn Sie das Map-Objekt selbst mit [placement new] (https://eigen.tuxfamily.org/dox/group__TutorialMapClass.html#title3) ändern, müssen Sie sich "nur" mit der Zuordnung/Freigabe der referenzierten Daten beschäftigen, besser, nicht nicht zufriedenstellend. – ggael

+0

Ihre vollständige Antwort ist einfach PERFEKT! Vielen Dank! – itQ