Pointer



  • Klaus82 schrieb:

    Wenn Objekte der GSL (z.B. ein acc oder spline ) woher kriege ich dann die Information der Größe?

    Also wie funktioniert dann der Kopiervorgang memcpy(spline2,spline,sizeof(?)).

    memcpy(spline2,spline,sizeof(*spline)
    

    Aber: Du kopierst einfach keine Strukturen/Klassen mit memcpy() , es sei denn Du weisst, dass eine shallow copy ausreicht.
    Wie Nathan schon sagt, gibt es in C++ Kopierkonstruktor und Zuweisungsoperator.

    Wenn ich bei der gsl bleibe: Hier ist die Definition von gsl_spline :

    typedef struct {
      gsl_interp * interp;
      double  * x;
      double  * y;
      size_t  size;
    } gsl_spline;
    

    Wenn Du so ein Ding mit memcpy() (shallow) kopierst hast Du zwei splines, die sich ein gsl_interp , ein array x und ein array y teilen.
    Das ist keine Kopie - das ist eher ein siamesischer Zwilling.



  • Ich weiß langsam nicht mehr so recht, wie ich es weiter beschreiben soll.

    Vielleicht mal umgekehrt: Ich habe eine Klasse, die einen Pointer auf einen spline enthält

    class someClass
    {
      someClass(const someClass&);
      gsl_spline *spline;
    };
    // Copy Constructor
    someClass::someClass(const someClass& rhs):spline(rhs.spline){}
    

    Diesen Copy Constructor müsste ich gar nicht so schreiben, weil er genau die shallow copy macht, die mir der Compiler generierte Copy Construtor auch liefern würde.

    Aber anhand des Beispiels von gsl_spline will ich doch folgendes:
    Lieber Copy Constructor,
    fordere den Speicher an, denn gsl_spline benöigt. Jetzt fange bei der Adresse von rhs.spline an und gehe so lange weiter bis du das Ende des Speicherblocks erreicht hast. Kopiere den Inhalt diesen abgelaufenen Speicherblocks in den eben angeforderten Speicher.
    Danke,
    dein Klaus.

    Und genau zu diesem Prozess kann ich mir den C++ Syntax nicht vorstellen. Ich könnte es mir mittels memcpy oder copy vorstellen, wenn ich die Größe des Speicherblocks ermitteln könnte.

    Ansonsten ...

    someClass::someClass(const someClass& rhs)
    {
      gsl_spline *spline;
      // jetzt kopiere den Inhalt des Speicherblocks auf den rhs.spline zeigt in den eben angeforderten Speicherblock auf den spline zeigt.
    }
    

    ... wie ist der Syntax für den Kommentar? Vielleicht sehe ich mittlerweile einfach den Wald vor lauter Bäumen nicht mehr.

    Gruß,
    -- Klaus.



  • Klaus82 schrieb:

    class someClass{
        someClass(const someClass& rhs);
        gsl_spline *spline;
    };
    someClass::someClass(const someClass& rhs){
        //gsl_spline *spline; //was sucht diese lokale variable hier?
        // jetzt kopiere den Inhalt des Speicherblocks auf den rhs.spline zeigt in den eben angeforderten Speicherblock auf den spline zeigt.
        spline = new spline(rhs.spline); //hätte man fast selbst drauf kommen können
        //this->spline = new spline(rhs.spline); //tut dasselbe, leuchtet aber vielleicht mehr ein
    }
    


  • nwp3 schrieb:

    Klaus82 schrieb:

    class someClass{
        someClass(const someClass& rhs);
        gsl_spline *spline;
    };
    someClass::someClass(const someClass& rhs){
        //gsl_spline *spline; //was sucht diese lokale variable hier?
        // jetzt kopiere den Inhalt des Speicherblocks auf den rhs.spline zeigt in den eben angeforderten Speicherblock auf den spline zeigt.
        spline = new spline(rhs.spline); //hätte man fast selbst drauf kommen können
        //this->spline = new spline(rhs.spline); //tut dasselbe, leuchtet aber vielleicht mehr ein
    }
    

    Wohl kaum. Vielmehr

    spline = new gsl_spline(*rhs.spline)
    

    Ich hoffe doch, dass someClass auch noch den passenden Destructor bekommt. Oder besser den passenden Smart-Pointer für spline...



  • Laut Furble Wurble, hat gsl_spline aber selber kei.en Copyctor, sondern macht dann auch nur ei.e shallow copy.
    Das heißt du hast zwei Möglichkeiten: Klasse moveonly machen oder Refcounting.
    Es sei denn es gibt eine copyspline Funktion, die die richtige Kopie macht.



  • Nathan schrieb:

    Laut Furble Wurble, hat gsl_spline aber selber kei.en Copyctor, sondern macht dann auch nur ei.e shallow copy.
    Das heißt du hast zwei Möglichkeiten: Klasse moveonly machen oder Refcounting.
    Es sei denn es gibt eine copyspline Funktion, die die richtige Kopie macht.

    Wir müssen zwei Dinge unterscheiden: Die gsl_spline-Objekte haben Pointer auf Objekte (x, y, interp), die sie selbst vermutlich nicht besitzen und die daher extern erzeugt und wieder zerstört werden müssen. (kenne jetzt den Hintergrund dieser Splines nicht).

    Die letzte Frage des TO bezog sich jedoch auf die Klasse someClass, die Pointer auf gsl_spline-Objekte als Member hat. So wie er die Frage gestellt hat, will er nur die gsl_spline-Objekte kopieren, die ihrerseits dann auf die gleichen Internas zeigen (ob er das wirklich will, ist eine andere Frage). Das hängt alles davon ab, ob gsl_spline per Definition Ownership über die x,y,interp-Objekte übernehmen soll oder nicht. Wenn ja, ist ein noch tieferes Copy angezeigt, und dann kommen deine Überlegungen zum Tragen.



  • Nathan schrieb:

    Laut Furble Wurble, hat gsl_spline aber selber kei.en Copyctor, sondern macht dann auch nur ei.e shallow copy.
    Das heißt du hast zwei Möglichkeiten: Klasse moveonly machen oder Refcounting.
    Es sei denn es gibt eine copyspline Funktion, die die richtige Kopie macht.

    Oder er baut sich halt einen Copy-Konstruktor für seine Spline-Struktur.
    Ist zwar in Klassen etwas sexier, geht aber auch in Strukturen. Oder er tut das Ding in einen shared_ptr, falls er nicht wirklich eine Kopie braucht, sondern nur einen "Link".



  • Guten Morgen,

    It0101 schrieb:

    Oder er tut das Ding in einen shared_ptr, falls er nicht wirklich eine Kopie braucht, sondern nur einen "Link".

    Nochmal zur Motivation: Ausgangspunkt ist firstprivate von Open MP, siehe hier.

    Ich versuche einen wrapper zu konzipieren, der einen Datensatz zur Interpolation beinhaltet, d.h. mittels des Datensatzes wird dieser spline initialisiert.

    Wenn ich firstprivate richtig verstehe wird ein Objekt 'in jeden Thread kopiert', d.h. jeder Thread hat seine eigene lokale Kopie. In der Beschreibung von firstprivate steht, dass dazu der Copyconstructor des Objekts aufgerufen wird - und an diesem Punkt stehe ich gerade: Ich verstehe das so, dass quasi in jedem Thread ein ihm eigenes Objekt über den Copykonstruktor initialisiert wird, d.h. jedes kopierte Objekt ist komplett selbst für seine Inhalte verantwortlich.

    Aus dem Grund denke ich auch, dass Referenzen ein Widerspruch sind, denn ich will nicht in jedem Thread ein Objekt, das über Referenzen auf das Ursprungsobjekt zugreift.

    Also benötige ich einen Move Constructor?

    Gruß,
    -- Klaus.



  • Die GSL bietet keine Funktion für eine tiefe Kopie eines gsl_spline -Objekts an. Aber das wäre genau das, was du willst (bzw zu wollen glaubst). Stattdessen musst Du wohl mit gsl_spline_alloc und gsl_spline_init arbeiten. Und dazu müsste man dann das Fucking Manual lesen.



  • So,
    ich denke ich habe es jetzt:

    Der Kopierkonstruktor kann leider nicht kopieren, aber mit dem Inhalt des zu kopierenden Objekts bin ich in der Lage im neuen Objekt neu zu initialisieren.

    Anbei noch der move constructor und move assignment operator.

    Jetzth habe ich doch aber alles, oder nicht?

    Und die magische Zeile 57

    acc(rhs.acc),spline(rhs.spline)
    

    funktioniert nun, weil ich interpolation als Rvalue caste? Als Lvalue würde es einfach die Adresse des einen Pointers in den anderen schreiben.

    /*
    interpolation.h
    */
    #ifndef INTERPOLATION_H_
    #define INTERPOLATION_H_
    
    #include <iostream>
    #include <vector>
    #include <gsl/gsl_spline.h>
    #include <gsl/gsl_errno.h>
    
    struct interpolation
    {
    	interpolation();
    	interpolation(std::vector<double>, std::vector<double>);
    	interpolation(const interpolation&);
    	interpolation& operator=(const interpolation&);
    	interpolation& operator=(interpolation&&);
    	interpolation(interpolation&&);
    	~interpolation();
    	double operator()(double);
    	std::vector<double> x,y;
    	gsl_interp_accel *acc;
    	gsl_spline *spline;
    };
    #endif
    
    /*
    interpolation.cpp
    */
    #include <iostream>
    #include "interpolation.h"
    /*
    ---{}--- default constructor ---{}---
    */
    interpolation::interpolation():x(),y(),
    acc(nullptr),spline(nullptr)
    {}
    /*
    ---{}--- constructor ---{}---
    */
    interpolation::interpolation(std::vector<double> x, std::vector<double> y):
    x(x), y(y),
    acc(gsl_interp_accel_alloc()),
    spline(gsl_spline_alloc(gsl_interp_cspline,x.size()))
    {
    	gsl_spline_init(spline,x.data(),y.data(),x.size());
    }
    /*
    ---{}--- copy constructor ---{}---
    */
    interpolation::interpolation(const interpolation& rhs):
    x(rhs.x),y(rhs.y),
    acc(gsl_interp_accel_alloc()),
    spline(gsl_spline_alloc(gsl_interp_cspline,x.size()))
    {
    	gsl_spline_init(spline,x.data(),y.data(),x.size());
    }
    /*
    ---{}--- assignment operator ---{}---
    */
    interpolation& interpolation::operator=(const interpolation& rhs)
    {
    	if( this != &rhs)
    	{
    		gsl_interp_accel_free(acc);
    		gsl_spline_free(spline);
    		x.clear();
    		y.clear();
    		x = rhs.x;
    		y = rhs.y;
    		acc = gsl_interp_accel_alloc();
    		spline = gsl_spline_alloc(gsl_interp_cspline,x.size());
    		gsl_spline_init(spline,x.data(),y.data(),x.size());
    	}
    
    	return *this;
    }
    /*
    ---{}--- move constructor ---{}---
    */
    interpolation::interpolation(interpolation&& rhs):
    x(rhs.x),y(rhs.y),
    acc(rhs.acc),spline(rhs.spline)
    {
    	rhs.acc = nullptr;
    	rhs.spline = nullptr;
    }
    /*
    ---{}--- move assignment operator ---{}---
    */
    interpolation& interpolation::operator=(interpolation&& rhs)
    {
    	if( this != &rhs)
    	{
    		gsl_interp_accel_free(acc);
    		gsl_spline_free(spline);
    		x.clear();
    		y.clear();
    		x = rhs.x;
    		y = rhs.y;
    		acc = gsl_interp_accel_alloc();
    		spline = gsl_spline_alloc(gsl_interp_cspline,x.size());
    		gsl_spline_init(spline,x.data(),y.data(),x.size());
    
    		rhs.x.clear();
    		rhs.y.clear();
    		gsl_interp_accel_free(rhs.acc);
    		gsl_spline_free(rhs.spline);
    		rhs.acc = nullptr;
    		rhs.spline = nullptr;
    	}
    
    	return *this;
    }
    /*
    ---{}--- destructor ---{}---
    */
    interpolation::~interpolation()
    {
    	gsl_interp_accel_free(acc);
    	gsl_spline_free(spline);
    }
    /*
    ---{}--- operator() ---{}---
    */
    double interpolation::operator() (double x)
    {
    	return gsl_spline_eval(spline,x,acc);
    }
    

    Gruß,
    -- Klaus.


Anmelden zum Antworten