2016-07-10 7 views
2

Hier ist der Code für eine Umformfunktion in Eigen. Es klappt.Erstellen einer Umformfunktion in Eigen

typedef MatrixXd mat; 
typedef VectorXd vec; 

Map<mat> reshape (vec b, const uint n, const uint m) { 
    return Map<mat>(b.data(), n, m); 
} 

Ich habe versucht, den richtigen Typ für das erste Argument zu entscheiden.

vec & b noch funktioniert, aber ich bekomme seltsame Fehler mit const vec & b oder const vec b:

error: invalid conversion from 'const Scalar* {aka const double*}' to 'Eigen::Map<Eigen::Matrix<double, -1, -1> >::PointerArgType {aka double*}' [-fpermissive] 
    return Map<mat>(b.data(), n, m); 
       ~~~~~~^~ 

Ich vermute, dies zu Veränderlichkeit fällig ist und der Tatsache, dass die reshape Funktion nicht neu Speicher zuteilt, aber ich würde lerne gerne eine detailliertere Erklärung.

Hmm, es scheint, dass vec && b der richtige Typ dafür ist, aber ich bin aus meiner Tiefe.

Antwort

3

Sie haben Recht, dass es sich um ein Problem mit der Wandlungsfähigkeit handelt. Wenn Sie const vec& verwenden, können Sie nur auf eine const mat wo es sich als

Map<const mat> reshape (const vec& b, const uint n, const uint m) { 
    return Map<const mat>(b.data(), n, m); 
} 

sonst hat man die Komponenten eines const vec über die abgebildeten Matrix verändern können. Es hat nichts mit der Speicherzuweisung zu tun.

Eigentlich sind beide vec und const vec falsch. Beide bedeuten die Abbildung auf eine temporäre Kopie des ursprünglichen Vektors, dessen Leben nach dem Funktionsaufruf endet, wie Avi Ginsburg sagte, was zu einem undefinierten Verhalten führt.

Bitte beachten Sie, dass der obige Code nur korrekt ist, wenn der Eingang ein Eigen::VectorXd ist.

Tatsächlich können sowohl vec& als auch const vec& falsch sein, wenn Ihre Eingabe b ein Ausdruck ist. Die Verwendung von vec& führt nicht zum Kompilieren, da die Komponenten eines Ausdrucks nicht veränderbar sind. Die Verwendung von erzwingt, dass der Ausdruck während des Funktionsaufrufs in einen temporären konstanten Vektor umgewandelt wird, und Sie ordnen ihn erneut einem Temp-Vektor zu.

Map<mat> reshape (vec& b, const uint n, const uint m) { 
    return Map<const mat>(b.data(), n, m); 
} 

Map<const mat> reshape_const (const vec& b, const uint n, const uint m) { 
    return Map<const mat>(b.data(), n, m); 
} 

vec a(100), b(100); 
Map<mat> c1 = reshap(a, 10, 10);     // ok 
Map<mat> c2 = reshap(a + b, 10, 10);    // error, expression not mutable 
Map<const mat> c3 = reshap_const(a, 10, 10);  // ok 
Map<const mat> c4 = reshap_const(a + b, 10, 10); // error, mapping to temp vec 

In diesem Fall können Sie den Ausdruck Typ als Parameter Typ verwenden müssen, obwohl Sie wahrscheinlich Ihre reshape mit Ausdrücken nicht benutzen zu. Sie können mehr Details hier finden.

http://eigen.tuxfamily.org/dox-devel/TopicFunctionTakingEigenTypes.html

2

Es ist nur eine Frage der Anwendungsbereich. Lassen Sie uns einen MCVE erstellen und zu erklären, dass verwendet werden:

#include <Eigen/Core> 
#include <iostream> 

using namespace Eigen; 

typedef MatrixXd mat; 
typedef VectorXd vec; 

Map<mat> reshapeCopy (vec b, const size_t n, const size_t m) { 
    return Map<mat>(b.data(), n, m); 
} 

Map<mat> reshape (vec &b, const size_t n, const size_t m) { 
    return Map<mat>(b.data(), n, m); 
} 

int main() 
{ 
    vec tr; 
    tr.setLinSpaced(4,1,4); 
    std::cout << tr << "\n\n"; 
    Map<mat> m = reshape(tr, 2,2); 
    std::cout << m << "\n\n"; 
    return 0; 
} 

Verwenden g ++ 4.9.3 auf Ubuntu Ausgänge:

4.94066e- 324 3
4.94066e-324 4

In reshapeCopy, b ist eine Kopie von tr. Seine Lebensdauer ist bis zum Ende der reshapeCopy Funktion. Bei Verwendung in main ist daher die Ausgabe ein Kauderwelsch/undefiniertes Verhalten. In der reshape Funktion wird tr durch Referenz übergeben und daher ist die b s Lebensdauer so lang wie tr und die Ausgabe ist wie erwartet.

kangshiyin ist zu Recht darauf hin, dass der spezifische Fehler Sie bekommen, wenn Sie die Funktion mit const vec b oder const vec &b definieren, die b ist const, heißt nicht wandelbar, und der Rückgabetyp ist ein veränderliches Map<mat>.