Übergabe eines vectors



  • Hi Leute,

    mir ist grad nicht ganz klar wie ein <vector> eigentlich an eine Funktion übergeben wird.

    Nehmen wir an ich übergebe einen Vector mit folgendem Code, also ganz simpel:

    foo(std::vector<double> megavector);
    

    Wird hier also der Vektor kopiert und in der Funktion mit einem "neuen" vector weiterverfahren. oder wird nur ein zeiger übergeben der dann praktisch auf denselben Speicherbereich zeigt?



  • Mal davon abgesehen dass du bei der Übergabe das "std::vector<double>" weglässt:

    Wird hier also der Vektor kopiert und in der Funktion mit einem "neuen" vector weiterverfahren

    Genau.
    Wenn du den selben vector haben willst musst du ihn per Referenz übergeben.



  • alles klar. Dann ergibt sich bei mir ein Problem, das ich grad nicht mehr durchschaue:

    Ich habe in einer Klasse 3 Verschiedene vectoren und eine Funktion die, jeweils einen zeiger auf diese Vektoren innerhalb eines Arrays zurückgibt:

    Header.h:
    
    class Klasse A{
    
    public:
    
    A();
    ~A();
    
    std::vector<double> *get_vector();
    
    private:
    
    std::vector<double> x;
    std::vector<double> y;
    std::vector<double> z;
    
    };
    
    Source.cpp:
    
    A::A(){
    
    x.push_back(0);
    y.push_back(0);
    z.push_back(0);
    
    }
    
    A::~A(){
    
    }
    
    std::vector<double> * A::get_vector(){
    std::vector<double> *ptr_to_vec = new std::vector<double>[3];
    
    ptr_to_vec[0] = x;
    ptr_to_vec[1] = y;
    ptr_to_vec[2] = z;
    
    return ptr_to_vec;
    
    }
    

    Schon hier stellt sich mir die Frage warum der Compiler keinen Fehler bei der get_vector() Funktion wirft, da ja eigentlich x, y und z so wie ich das sehe keine zeiger bilden, oder doch?

    Jetzt kommt das eigentliche Problem (bei dem der Compiler dann auch meckert). Ich rufe in einer anderen Funktion die get_vector() Funktion auf um an die einzelnen Vektoren zu kommen. Diese Funktion sollte also Zeiger annehmen und dann irgendwas mit den Dingern machen. Das ist bei mir folgendermaßen Deklariert:

    double *make_array(std::vector<double> *_components[3]);
    

    Wenn ich nun hierrauf die get_vector() Funktion anwende, dann meckert der Compiler:

    "IntelliSense: Das Argument vom Typ ""std::vector<double, std::allocator<double>> *"" ist mit dem Parameter vom Typ ""std::vector<double, std::allocator<double>> **"" inkompatibel."

    was mach ich falsch?



  • Was hat dieses Pointer- und Arraygefrickel mit der Ausgangsfrage zu tun?

    Zum Problem: die Funktion make_array will ein Array von Pointern auf vector (vector**), du lieferst aber einen Pointer auf vector (vector*).



  • Das ist ja irgendwie Kraut und Rüben. Eine Mischung zwischen vector und Zeiger ist schon sehr unübersichtlich. Da wundert es mich nicht, wenn Du da durcheinander kommst. Ich versuche mal ein paar Sachen zu korrigieren.

    std::vector<double> * A::get_vector(){
    std::vector<double> *ptr_to_vec = new std::vector<double>[3];
    
    ptr_to_vec[0] = x;
    ptr_to_vec[1] = y;
    ptr_to_vec[2] = z;
    

    "ptr_to_vec" ist ein Zeiger auf ein Array und jedes Element ist ein std::vector<double> und damit ist die Zuweisung erlaubt. Sieht zwar ziemlich unsinnig aus aber syntaktisch korrekt.

    In der Funktion fehlt das return und damit wird ein ungültiger Zeiger geliefert. Und der ptr_to_vec wird auch nirgends gelöscht. Damit entsteht zwangsweise ein memoryleak.

    double *make_array(std::vector<double> *_components[3]);
    

    Das ist unklar. Was ist _components? Wie wendest Du die get_vector-Funktion an? Ein vollständigeres Beispiel wäre hilfreich.

    Und schau mal, dass Du Deinen Sourcecode besser einrückst. So ist er noch schwerer nachzuvollziehen.


  • Mod

    Hier geht noch viel mehr durcheinander, als nur Zeiger und vector (was schon ganz schön schlimm ist). Aufgrund der Namen der Funktionen und Variablen habe ich den starken Verdacht, dass hier das geplante Verhalten und die Programmlogik überhaupt nicht zusammen passen.

    @Threadersteller: Soll die Klasse A zufällig eine Art mathematischer Vektor oder Matrix sein? Falls ja, dann müsste man das Programm von Grund auf anders gestalten. Falls nein, dann müsste man das Programm höchstwahrscheinlich auch von Grund auf anders gestalten (wegen der Pointerfrickelei), aber du müsstest uns noch erklären, was A sein soll.



  • Ich gebe zu meine Beschreibung ist ein wenig irreführend... Es war schon spät, ich werd mich mal an einer ordentlichen Erklärung versuchen:

    Was ich als Klasse A bezeichne ist in Wirklichkeit eine Klasse die ich für die Beschreibung von verschiedenen Koordinatensystemen verwende. Jeder Vektor steht dabei für die Komponenten in einer der jeweiligen Achsen des Koordinatensystems.

    Nun brauche ich für u.a. die Integration von Beschleunigungen die jeweiligen Komponenten des Vektors. Da die Vektoren sehr lang werden möchte ich bei der Übergabe möglichst keine Kopien übergeben (darauf bezog sich dann auch die erste Frage) sondern mit Zeigern arbeiten.

    Der nächste Punkt ist nun, dass ich das auch möglichst in einem Schritt machen will. Meine Idee war also ein Feld aus Zeigern zu erstellen. Diese Zeiger zeigen dann einfach auf die Vektoren, die Funktion get_vector() gibt das Feld zurück und ich kann sie einfach verwenden. Ich hielt das gestern Abend noch für eine simple Lösung.

    Dass die Namen der Funktionen usw. nicht zusammenpassen hat den Hintergrund, dass ich gestern Abend die Hälfte reinkopiert und die Hälfte schnell runtergetippt habe, daher passt das ganze nicht so zusammen, also vergesst das.

    Falls etwas unklar ist oder noch Code benötigt wird sagt Bescheid, aber im Grunde sieht mein Code (bis auf die Namen der Funktionen) mit dem überein was ich gepostet habe.

    @SeppJ was meinst du mit grundlegend anders gestalten? Die Klasse A ist tatsächlich im Grunde ein Vektor (es existieren noch andere "Vektor" klassen, die alle von derselben Basisklasse abstammen und sich im Bezugssystem unterscheiden. Ich hielt es für eine gute Idee das so aufzuziehen, allerdings fehlt mir wahrscheinlich die Erfahrung beim programmieren um mögliche Probleme bereits von Vornherein zu erkennen. Was wäre dein Vorschlag für eine sinnvolle Strukturierung?

    EDIT:://
    @tntnet Ich hab natürlich auch ein return in meinem Code ich werd das schnell ergänzen.


  • Mod

    @SeppJ [...] Was wäre dein Vorschlag für eine sinnvolle Strukturierung?

    Kannst du das folgende nochmal erläutern? Ganz genau? Nicht in Form von Code, sondern als Mathematik ausgedrückt.

    Freddy_Kay schrieb:

    Was ich als Klasse A bezeichne ist in Wirklichkeit eine Klasse die ich für die Beschreibung von verschiedenen Koordinatensystemen verwende. Jeder Vektor steht dabei für die Komponenten in einer der jeweiligen Achsen des Koordinatensystems.



  • SeppJ schrieb:

    @SeppJ [...] Was wäre dein Vorschlag für eine sinnvolle Strukturierung?

    Kannst du das folgende nochmal erläutern? Ganz genau? Nicht in Form von Code, sondern als Mathematik ausgedrückt.

    Freddy_Kay schrieb:

    Was ich als Klasse A bezeichne ist in Wirklichkeit eine Klasse die ich für die Beschreibung von verschiedenen Koordinatensystemen verwende. Jeder Vektor steht dabei für die Komponenten in einer der jeweiligen Achsen des Koordinatensystems.

    Na, er meint, dass er die Achsen durch Vektoren beschreibt. Was an sich komisch ist, die Achsen sind doch Richtungsvektoren

    (100)(010)(001)\begin{pmatrix} 1 \\ 0 \\ 0 \end{pmatrix} \begin{pmatrix} 0 \\ 1 \\ 0 \end{pmatrix} \begin{pmatrix} 0 \\ 0 \\ 1 \end{pmatrix}

    Außer er beschreibt die Achsen von lokalen Koordinatensystemen in globaleren. Sprich, er beschreibt mit Richtungsvektoren die einzelnen Achsen lokalerer Koordinatensysteme...
    (Zuerst die ersten beiden, und dann die dritte durch Kreuzprodukt)

    Aber dazu soll er was sagen.



  • es ist weniger eine mathematische Einordnung als mehr eine technische.

    Es gibt bei mir 4 Bezugssysteme, die jeweils mit 3 Koordinaten beschrieben werden:
    1. Geozentrisch Inertial
    2. Geozentrisch mitrotierend
    3. Geografisch
    4. Äquatorial

    Mathematisch unterscheiden sie sich nicht wirklich, wenn man davon absieht, dass Geografische und Äquatoriale Koordinaten sphärische Koordinaten sind (in Länge/Breite (jeweils °) und Höhe in Metern) während der Rest in "klassischen" kartesischen Koordinaten angegeben wird.
    Sie unterscheiden sich eher technisch in der Definition der Bezugssysteme. Bei allem fällt die Hauptebene mit der Äquatorebene zusammen. Der Ursprung liegt bei allen im Erdmittelpunkt bzw. Geodätischen Mittelpunkt (wobei das eher schon ein Detail ist). Die z-Achse zeigt nich Norden und ist senkrecht auf der Hauptebene. Beim Inertialen (und ich glaub auch beim Äquatorialen) Koordinatensystem zeigt die x-Achse in Richtung einer Fixpunktes (Frühlingspunkt für die Experten unter euch). Beim geozentrisch mitrotierendem System und beim geografischem System zeigt die x-Achse in Richtung Nullmeridian.

    Ich verwende verschiedene bereits implementierte Modelle, die unter anderem das Erdschwerefeld berechnen, den Luftwiderstand, Sonneneinstrahlung etc. Jedes davon benötigt Angaben über Position und/oder Geschwindigkeit eines Objektes in unterschiedlichen Bezugssytemen.

    Damit ich nicht durcheinander komme und immer korrekte Angaben bezüglich der Koordinaten mache, habe ich die Koordinaten als eigene Klassen implementiert. Dort sind dann auch die einzelnen Umrechnungen zwischen den Systemen implementiert, so dass ich einen Koordinatensatz in einen anderen "casten" kann.

    EDIT:://
    @Sone
    Die einzelnen Vektoren die oben als x/y/z bezeichnet sind. Sollen bilden als ganzes mehrere Vektoren. Das meine ich folgendermaßen:

    Nehmen wir an x y z haben jeweils 10 Einträge. Das entrpsicht am Ende also 10 Vektoren:

    \vec{Vektor[0]} = \left(\begin{array}{c} x[0] \\ y[0] \\ z[0]\end{array}\right)

    der Zweite wäre dann:
    \vec{Vektor[1]} = \left(\begin{array}{c} x[1] \\ y[1] \\ z[1]\end{array}\right)

    usw.


  • Mod

    Freddy_Kay schrieb:

    Die einzelnen Vektoren die oben als x/y/z bezeichnet sind. Sollen bilden als ganzes mehrere Vektoren. Das meine ich folgendermaßen:

    Nehmen wir an x y z haben jeweils 10 Einträge. Das entrpsicht am Ende also 10 Vektoren:

    \vec{Vektor[0]} = \left(\begin{array}{c} x[0] \\ y[0] \\ z[0]\end{array}\right)

    der Zweite wäre dann:
    \vec{Vektor[1]} = \left(\begin{array}{c} x[1] \\ y[1] \\ z[1]\end{array}\right)

    usw.

    Da haben wir schon die ersten, offensichtlichen Verbesserungen:
    1. Warum dann nicht vector<array<double, 3>> ?
    2. Deine Implementierung passt nicht zu dem, was du beschreibst. Besonders nicht dein Konstruktor und nicht dein get_vector.
    3. Dein get_vector vereinfacht sich dann auf

    const vector<array<double, 3>>&    // Hier besser ein typedef.
     get_vector() const { return koordinatenvector; }
    

    4. Dein Konstruktor vereinfacht sich dann auf ungefähr gar nichts. Was übrigens sehr oft der Normalfall ist.
    5. Dein Destruktor war ja ohnehin schon zurecht leer -> Kommt auch weg.



  • zu 1.: Das löst mein Problem auf den ersten Blick erstmal. Werd ich ausprobieren.
    zu 2.: Der Konstruktor ist exemplarisch. Dort werden andere Werte eingetragen u.a. der Initialvektor. Es gibt aber auch einen leeren Standartkonstruktor.
    zu 3.: Jop macht sich ganz gut, werd ich denke ich so übernehmen. Danke dafür!
    zu 4.: Seh ich ein. Hab so einen auch drin. Wie gesagt nur exemplarisch gewesen.
    zu 5.: Darf man das einfach? Mein Compiler meckert wenn ich eine Funktion deklariere die ich dann nicht definiere.

    Das mit dem array war mir neu. Denke aberist genau das was ich gebrauchen kann, dann erübrigt sich das Zeigergedöns. Danke dir!



  • Freddy_Kay schrieb:

    zu 5.: Darf man das einfach? Mein Compiler meckert wenn ich eine Funktion deklariere die ich dann nicht definiere.

    nein, aber mam muss keinen Destruktor deklarieren.


  • Mod

    Freddy_Kay schrieb:

    zu 2.: Der Konstruktor ist exemplarisch. Dort werden andere Werte eingetragen u.a. der Initialvektor.

    Gut.

    Es gibt aber auch einen leeren Standartkonstruktor.

    Und der ist dann wozu da? Damit du versehentlich leere Objekte erstellen kannst? Wenn ein Konstruktor ein Objekt nicht so initialisiert, dass man damit arbeiten kann, ist er ein guter Kandidat zum Rausstreichen.

    zu 5.: Darf man das einfach? Mein Compiler meckert wenn ich eine Funktion deklariere die ich dann nicht definiere.

    Warum deklarierst du ihn denn? Lerne folgende wichtige(!) Regel der Sprache:
    http://en.wikipedia.org/wiki/Special_member_functions

    Falls du die Idee mit dem leeren Destruktor aus einem Lehrbuch/Tutorial haben solltest: Das Buch taugt nichts. Steht wahrscheinlich noch viel sonstiger Unsinn drin. Wegschmeißen. Gibt's leider viel zu oft.



  • Danke für den Link. Gabs einiges was mir so nciht bekannt war.

    Ich hab mir mein C++ Wissen übrigens aus dem Internet zusammengesucht... Komme eigentlich von Interpretersprachen wie Matlab. Hab auch mal Visual Basic gemacht. C++ ist da schon ein ganz schöner Umstieg. Hiflt mir auf jeden Fall erstmal weiter. Ich bedanke mich.


Log in to reply