Kopierkonstrukter für Zeiger



  • hi,

    hab hier eine Situation wo ich einem Arrayplatz ein Zeiger zuweisen möchte. Was aber so nicht geht, da mein Array keine Zeiger aufnimmt. Also müsste *s nehmen um das fehlerfrei zu kompilieren - dann schlägt aber der Kopierkonsturktor zu und erstellt ordnungsgemäß ein objektkopie.
    Kann ich dieses Verhalten abstellen? oder kann man den zuweisungsoperator für pointer überladen?

    void Collection::add(Set * s)
    {	
    	printf("Fuege Set-ID %i in Collection ein\n", s);
    	if (m_sets == 0)
    		m_sets = new Set[CUR_MAX];
    
    	if (m_count == CUR_MAX)
    		resize();
    
    	m_sets[m_count++] = s;  //<- Ich möchte kein neues Objekt
    }
    


  • Kopierkonstruktor-opfer schrieb:

    hab hier eine Situation wo ich einem Arrayplatz ein Zeiger zuweisen möchte. Was aber so nicht geht, da mein Array keine Zeiger aufnimmt.

    Und was dann? Birnen, Tomaten? An deinen Codebeispiel kann man dies nicht sicher ablesen. Ich rate mal, das dein Array vom Typ Set[] ist (Heißt aber auch das Polymorphie etc. nicht funktioniert und immer wirklich Set-Objekte verwendet werden sollen).

    Kopierkonstruktor-opfer schrieb:

    Also müsste *s nehmen um das fehlerfrei zu kompilieren - dann schlägt aber der Kopierkonsturktor zu und erstellt ordnungsgemäß ein objektkopie.

    Ich würde eigentlich eher auf den Zuweisungsoperator tippen, da in dem Array ja wohl Objekte liegen.

    Der folgende Code ruft nicht einmal den Kopierkonstruktor auf, sondern wie zu erwarten:
    3 x Konstruktor
    1 x Zuweisungsoperator
    3 x Destruktor

    #include <iostream>
    
    class Dummy
    {
    public:
        Dummy() {
            std::cout << "Dummy::Dummy" << std::endl; }
        ~Dummy() {
            std::cout << "Dummy::~Dummy" << std::endl; }
        Dummy(Dummy const &) {
            std::cout << "Dummy::Dummy(Dummy const &)" << std::endl; }
        Dummy& operator=(Dummy const &)	{
    		std::cout << "Dummy::operator=" << std::endl;
    	    return *this; }
    };
    
    int main()
    {
    	Dummy * dummy = new Dummy();
    
    	Dummy array[2];
    	array[0] = *dummy;
    
    	delete dummy;
    }
    

    cu André



  • Du erzeugst doch gar nix mit dem Copy Constructor?! Ueberlade einfach den operator= fuer

    Set *s
    

    und was eben damit gemacht werden soll, wenn Dir das Default Verhalten offenbar gefaellt.

    Eine andere Sache die ich grad sehe, gibst Du da die Speicheradresse von Deinem Set-objekt aus und nennst das "Set-ID", oder taeusche ich mich? Muesste das nicht *s heissen? Evtl brauchst Du dafuer aber zusaetzlich einen operator<< um zu sagen, wass denn genau von der Klasse "Set" im Zusammenhang mit operator<< ausgegeben werden soll, oder Du musst das irgendwie spezifizieren, derart..

    s->ID
    

    (und warum eigentlich printf?!)

    🙂



  • Also ich hab jetzt nochmal von vorn angefangen, leider ohne erfolg.

    ich hab einen "Wert" in einem Array, auf den soll ich über das Array zugreifen können und in einer LookUpTable soll der Pointer ebenfalls vorhanden sein.
    (Das ganze soll, wenn es klappen würde, mal in einer UnionFind Klasse enden)

    Aber durch die Zuweisungsgeschichte wird ein nues Objekt erzeugt und der Pointer den ich in der Lookuptabelle hab zeigt dann zwar auf ein objekt mit selben wert, aber nicht auf das selbe objekt.

    hier mal ein paar schnippsel, ws ich will, das am ende der Zeiger "t", sowohl dem Array, als auch der LookUpTable hinzugefügt wird.

    void UnionFind::makeSet(int x)
    {
    	Set * t = new Set(false, x);
    	printf("makeSet() alloc auf %i\n", t);
    	m_coll->add(t);  //Array hinzufügen
    	m_lut->insert(t); //LookUpTable hinzufügen
    	vec.push_back(t);
    }
    //Pointer schreibweise funktioniert leider nicht - wie müsst es richtig aussehen?
    void Collection::add(Set * s)
    {	
    	printf("Fuege Set-ID %i in Collection ein\n", &s);
    	if (m_sets == 0)
    		m_sets = new Set[CUR_MAX];
    
    	if (m_count == CUR_MAX)
    		resize();
    
    	m_sets[m_count++] = s; //Zeigerverwendung = Kompilierfehler
    }
    
    //Dieser Veruch eines Überladenen Zuweisungsoperator für Pointer lässt sich nicht kompiliere
    Collection * Collection::operator=(const Collection * rhs)
    {
    	printf("Collection Assignment Operator!\n");
    
    	return rhs;
    }
    

    An diesem Nadelöhr hab ich jetzt mit sicherheit schon 6-7 stunden verbracht - das muss das irgenwie zu lösen sein. der soll einfach keine kopien erstellen sondern mit dem orignal arbeiten.



  • Sehe ich das jetzt richtig, dass Du ein Objekt in einen Container einfügen willst, das Objekt aber nicht kopieren willst, sondern nur eine Referenz auf das gleiche Objekt abspeichern?
    Das ist kein Problem - allerdings nur explizit. Du musst den Container von vornherein mit pointern füllen und dann weitere Zeiger einfügen. Es gibt nur zwei Möglichkeiten der Speicherung: By value und by reference. Die kannst Du nicht mischen.
    Was Du noch machen könntest wäre in die objekte, die du speichern willst, einen angepassten Kopiermechanismus einzubauen. Also die eigentlichen Daten nochmal kapseln und dann bei einer Objektkopie nur wieder auf die gleichen Daten verweisen. So macht es z.B. die std::string - Klasse (allerdings nur bis zur ersten Änderung an den Daten. Dann wird kopiert). Das ist allerdings eine Sache, die sehr sorgfältig implementiert werden muss, sonst hast Du völliges Durcheinander.



  • Wirdbald schrieb:

    ...So macht es z.B. die std::string - Klasse (allerdings nur bis zur ersten Änderung an den Daten. Dann wird kopiert)...

    Nur als Anmerkung: Das was du hier beschreibst, macht std::string nicht zwangsweise (Implementierungsabhängig und nicht vom Standard festgelegt).

    cu André



  • Zuerst einmal: wenn du beschreibst, was du erreichen möchtest, statt was du tun möchtest, dann kann dir besser geholfen werden. Es sieht so aus, als ob du etwas auf einem äußerst ungewöhnlichen Weg erreichen willst, und ungewöhnliche Methoden bedeuten meist, dass sie nicht gut verstanden werden (und deshalb schlecht wartbar, schlecht nachvollziehbar und schlecht anwendbar sind), und dass es eine bessere Methode gibt (sonst wäre deine Methode ja nicht ungewöhnlich). Ein ganz starkes Indiz dafür ist deine operator=-Überladung mit einem Pointer, die ist nicht nur ungewöhnlich sondern grauenvoll. Überleg mal was passiert wenn man sowas wie a = b = c schreibt...

    Dann noch eine Anmerkung (wundert mich dass die bisher noch nicht gefallen ist): Wenn du C++ programmierst, dann lass bitte printf() ganz weg. printf() ist C und wird in C++ durch den std::cout Stream ersetzt. Der ist typsicher, die Syntax lesbarer, und sein Kollege sprintf() hat zusätzlich noch das Problem mit fehlenden Längenchecks, Speicherzugriffsfehlern usw.



  • denke ein array von pointern ist eher das was ich will. aber das funktioniert so wie es mache auch nicht

    class Set
    {
    public:
    	Set();
    	Set(int x);
    .........
    private:
    	void resize();
    	SetMember * m_elements; //Pointer auf SetElemnte
    	int   m_count;  //Anzahl Elemente der Menge
    	int   CUR_MAX;
    };
    ---------------------
    Set::Set(int x):m_count(0), CUR_MAX(1)
    {
    	m_elements[CUR_MAX];  //Hole mir Platz für CUR_MAX-Pointer
    	SetMember * s = new SetMember(x); //Erzeuge neues Objekt 
    	m_elements[m_count] = s;  //Zuweisen - tut es nicht, kompilerfehler-wieso?
    }
    

    zu dem teil was ich erreichen möchte:



  • @pumukl: printf" stammt aus "C" und kann wie "cout" zur Ausgabe im Konsolen-Fenster in "C++" benutzt werden.
    Was ich aber eigendlich sagen will: "Wer "C" nicht kann, kann "C++" auch nicht."
    und
    "Wer "C++" vertreten will und über "C" schlecht redet, sollte besser schweigen."
    🙂



  • gg schrieb:

    Was ich aber eigendlich sagen will: "Wer "C" nicht kann, kann "C++" auch nicht."

    Interessant, ich habe nie wirklich C gelernt, und galt in den letzten 3 Firmen als der C++ Spezialist (Okay, liegt vielleicht auch einfach daran das es kaum echte Konkurenz gab, den wer in der IT aufhört zu lernen ist keine Konkurrenz).

    cu André



  • ich bin umgeben von spezialisten und keiner kann was zu meinem spezialproblem beitrage.....d.h. es ist unlösbar?



  • Lasst doch diesen C vs. C++ - Streit. Der gehört nicht hierher. printf() hat hier und da seine Berechtigung. Hier ist es jetzt unerheblich, es geht um was Anderes.

    Der Fehler oben ist, dass Du nur einen einzelnen Member-Pointer speicherst und kein array. m_elements müsste so deklariert werden:

    SetMember** m_elements;
    

    Viel besser wäre aber folgende Variante:

    std::vector<SetMember*> m_elements;
    


  • Ach, was mir gerade einfällt: Du nennst die Klasse "Set". Heißt das, Du möchtest einen eigenen Container implementieren, welcher eine Menge abbildet? Dann sind arrays ungeeignet. Vielmehr musst Du Dir dann über Hashing-Algorithmen, Binärbäume usw. Gedanken machen. Oder std::set benutzen.



  • ja das ganze soll in 20.0000 Jahren in einr UnionFind Struktur enden.

    d.h ich muss eine Collection abbilden können die aus mehreren Sets besteht (wobei ein Set aus x-SetMembern besteht)



  • gg schrieb:

    @pumukl: printf" stammt aus "C" und kann wie "cout" zur Ausgabe im Konsolen-Fenster in "C++" benutzt werden.
    Was ich aber eigendlich sagen will: "Wer "C" nicht kann, kann "C++" auch nicht."

    Falsch würde ich mal sagen - ich wüsste sicher für viele Problemstellungen keine Lösung in C, die mich zufriedenstellen würde, wohl aber in C++.
    Es gibt wahnsinnig viele Programmiertechniken etc, die man in C++ nie braucht, und mir beim Lesen von C - Code aufgefallen sind.
    Ich kann sicher mit C nicht die gleichen Programme schreiben, wie mit C++.

    gg schrieb:

    "Wer "C++" vertreten will und über "C" schlecht redet, sollte besser schweigen."
    🙂

    wiederum sehr kritisch zu betrachten - vieles lässt sich in C nur extrem hässlich lösen (schau dir nur mal den Linux-Kernel an, was da abgeht, um Dinge wie Objektorientierung nachzubilden etc., ist echt nicht mehr feierlich -- in C++ wäre vieles viel einfacher und besser zu lösen gewesen)



  • Wenns um einen Container für Pointer geht, warum dann keine std::Container? oder einen der boost::pointer_container.

    gg schrieb:

    @pumukl: printf" stammt aus "C" und kann wie "cout" zur Ausgabe im Konsolen-Fenster in "C++" benutzt werden.

    Ist mir bekannt. Es gibt auch diverse andere Dinge in C++, die man auch in C machen kann. Trotzdem gibt es Gründe, die Features von C++ zu nutzen. Gründe dagegen gibts nur ganz selten und in Spezialfällen (will mir grad keiner einfallen, aber ich schließ es mal nicht aus). statt std::vector kann man z.B. auch einfach dynamische C-Arrays nutzen und sich eine zusätzliche Variable nehmen um sich die Länge zu merken. Tut man aber nicht, weils nicht so bequem und sicher ist. Klar kann man printf() benutzen. Tut man aber auch nicht, vor allem weils nicht typsicher ist.

    Was ich aber eigendlich sagen will: "Wer "C" nicht kann, kann "C++" auch nicht."

    Halte ich fürn Gerücht. Man lernt natürlich mit der Zeit genug Details um C weitgehend zu verstehen, aber richtig können muss mans deshalb noch lange nicht. Sonst gehts gleich weiter "Wer Assembler nicht kann, kann C auch nicht..."

    "Wer "C++" vertreten will und über "C" schlecht redet, sollte besser schweigen." 🙂

    Niemand redet hier schlecht über C. C hat seine Daseinsberechtigung, genau wie andere Sprachen. Es gibt auch Stellen, wo C in C++-Quellcode seine Daseinsberechtigung hat, nur nicht dort, wo jemand es einfach aus Unkenntnis oder alter Gewohnheit an Stelle der entsprechenden C++-Features benutzt. Morgen kommt dann jemand und benutzt inline Assembler weil ihm entfallen ist, dass C++ bitshift-operatoren hat oder ähnliches, ist ja auch legal... 😉


Log in to reply