2017-09-05 5 views
2

Est-il possible de définir un pointeur vers un objet Eigen :: Map? Le code d'origine est assez complexe, mais voici ce que je suis en train de réaliser (code pseudo)C++ pointeur propre vers un objet Eigen :: Map <Eigen :: VectorXd>

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? 

}; 

Répondre

0

tout d'abord pas besoin d'utiliser des pointeurs ici parce que la carte est déjà essentiellement un pointeur, il serait plus simple si la mise à jour l'objet Carte avec placement new. Néanmoins, votre conception actuelle nécessiterait une allocation dans testfunction1 et une allocation dans testfunction2 au cas où elle aurait été allouée, ce qui n'est pas vraiment sûr. Il vaudrait donc mieux adopter une conception fonctionnelle en mettant « certains calculs » dans une fonction (ou un lambda nommé), faire testfunction1 retour par valeur:

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

Si vous voulez vraiment garder votre logique actuelle, alors voici une auto par exemple à l'aide -contained placement nouvelle:

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

ce qui est assez mauvais, car il peut fuir si une exception est levée lors de l'utilisation X. Vous pouvez contourner la gestion de la mémoire manuelle en demandant testFunction1 de retourner un VectorXd (ou quoi que ce soit qui gèrent la mémoire allocation/désallocation en soi) et faire le placement nouveau dans la fonction principale 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; 
} 

Enfin, si le contenu de X doit être en lecture seule, puis utilisez Map<const VectorXd> et non const Map<VectorXd> comme dans votre question initiale.

+0

Merci pour votre réponse. C'est ce que fait mon code actuel, mais cela rend la lecture difficile car l'instruction if else nécessite une fonction différente, mais j'accepte votre réponse car elle peut être utile aux autres. Cependant, je me demande encore comment déclarer un pointeur sur Map <...> – itQ

+0

Rien de compliqué, il suffit de déclarer 'typedef const MapVectorXd ConstMapVectorXd; 'puis d'utiliser' ConstMapVectorXd * ', mais vous devez gérer une allocation de mémoire dynamique complexe pour les données référencées par la nouvelle carte et l'objet Map lui-même, qui est toujours sujette à des erreurs et des fuites de mémoire. Si vous modifiez l'objet Map lui-même à l'aide de [placement new] (https://eigen.tuxfamily.org/dox/group__TutorialMapClass.html#title3), vous devrez "seulement" gérer l'allocation/désallocation des données référencées, mieux, pas satisfaisant. – ggael

+0

Votre réponse complète est juste PARFAIT! Merci beaucoup! – itQ