<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[[Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche]]></title><description><![CDATA[<p>Ich schreibe ein Programm, das Atome und Moleküle verwaltet.</p>
<p>EIn Atom kann mit einem anderen Atom chemisch verbunden sein. Dafür möchte ich mir die Adresse des anderen Atoms abspeichern.<br />
Grober Aufbau der Klasse.</p>
<pre><code class="language-cpp">class Atom
{
protected:
	double x;
	double y;
	double z;

	std::list&lt;Atom* &gt; neighbours;

public:
	Atom();
	virtual ~Atom();
	virtual void connect(Atom&amp; atom);
	virtual void disconnect(Atom&amp; atom);

};

// cpp - File
Atom::~Atom()
{
	for(std::list&lt;Atom*&gt;::iterator iter = neighbours.begin(); iter != neighbours.end(); iter++)
	{
	    disconnect(**iter);
	}
}
void Atom::connect(Atom&amp; atom)
{
    this-&gt;neighbours.push_back(&amp;atom);
    atom.neighbours.push_back(this);
}

void Atom::disconnect(Atom&amp; atom)
{
    this-&gt;neighbours.remove(&amp;atom);
    atom.neighbours.remove(this);
}
</code></pre>
<p>Ein Molekül besteht aus einem Vector von Atomen</p>
<pre><code class="language-cpp">class Molecule
{
protected:
	std::vector&lt;Atom&gt; atoms;
	void addAtom(const Atom&amp;);
};

void Molecule::addAtom(const Atom&amp; atom)
{
	atoms.push_back(atom);
}
</code></pre>
<p>Für Testzwecke möchte ich mir nun in einer Funktion zwei Testmoleküle erzeugen</p>
<pre><code class="language-cpp">createMolecule(string path)
{
	Molecule m;
	if (path == &quot;&quot;)
	{
		Atom a;
		a.setPosition3d(1,0,0);
		Atom b;
		b.setPosition3d(0,1,0);

		//-&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;  
                a.connect(b);

		m.addAtom(a);
		m.addAtom(b);
	}
	else
	{
		Atom a;
		a.setPosition3d(2,3,0);
		Atom b;
		b.setPosition3d(1,1,0);

		m.addAtom(a);
		m.addAtom(b);
	}
	return m;
}

int main()
{
 Molecule a = createMolecule(&quot;&quot;);
 Molecule b = createMolecule(&quot;irgendwas&quot;);
 // tu was mit a und b---
 return 0;
}
</code></pre>
<p>Wenn ich das ausführe bekomme ich ganz einfach Speicherzugriffsfehler.<br />
Das liegt höchstwahrscheinlich an den Zeigern, die ich speichere.<br />
Ich sehe im Moment aber noch nicht die ganze Ursache, vermute aber irgendwelche<br />
Kopierereien und Zeiger auf nicht-mehr-gültige Objekte.</p>
<p>Kann mir jmd sagen, was ich falsch mache und wie ich das besser hinbekomme?</p>
<p>Eine konkrete Frage wäre auch, ob std::list&lt;Type&gt;.push_back( const Referenz auf Type) eine Kopie einfügt oder nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/299885/anfängerproblem-zeiger-referenzen-und-gültigkeitsbereiche</link><generator>RSS for Node</generator><lastBuildDate>Thu, 13 Aug 2026 01:33:57 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/299885.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 20 Feb 2012 14:33:43 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 14:33:43 GMT]]></title><description><![CDATA[<p>Ich schreibe ein Programm, das Atome und Moleküle verwaltet.</p>
<p>EIn Atom kann mit einem anderen Atom chemisch verbunden sein. Dafür möchte ich mir die Adresse des anderen Atoms abspeichern.<br />
Grober Aufbau der Klasse.</p>
<pre><code class="language-cpp">class Atom
{
protected:
	double x;
	double y;
	double z;

	std::list&lt;Atom* &gt; neighbours;

public:
	Atom();
	virtual ~Atom();
	virtual void connect(Atom&amp; atom);
	virtual void disconnect(Atom&amp; atom);

};

// cpp - File
Atom::~Atom()
{
	for(std::list&lt;Atom*&gt;::iterator iter = neighbours.begin(); iter != neighbours.end(); iter++)
	{
	    disconnect(**iter);
	}
}
void Atom::connect(Atom&amp; atom)
{
    this-&gt;neighbours.push_back(&amp;atom);
    atom.neighbours.push_back(this);
}

void Atom::disconnect(Atom&amp; atom)
{
    this-&gt;neighbours.remove(&amp;atom);
    atom.neighbours.remove(this);
}
</code></pre>
<p>Ein Molekül besteht aus einem Vector von Atomen</p>
<pre><code class="language-cpp">class Molecule
{
protected:
	std::vector&lt;Atom&gt; atoms;
	void addAtom(const Atom&amp;);
};

void Molecule::addAtom(const Atom&amp; atom)
{
	atoms.push_back(atom);
}
</code></pre>
<p>Für Testzwecke möchte ich mir nun in einer Funktion zwei Testmoleküle erzeugen</p>
<pre><code class="language-cpp">createMolecule(string path)
{
	Molecule m;
	if (path == &quot;&quot;)
	{
		Atom a;
		a.setPosition3d(1,0,0);
		Atom b;
		b.setPosition3d(0,1,0);

		//-&gt;&gt;&gt;&gt;&gt;&gt;&gt;&gt;  
                a.connect(b);

		m.addAtom(a);
		m.addAtom(b);
	}
	else
	{
		Atom a;
		a.setPosition3d(2,3,0);
		Atom b;
		b.setPosition3d(1,1,0);

		m.addAtom(a);
		m.addAtom(b);
	}
	return m;
}

int main()
{
 Molecule a = createMolecule(&quot;&quot;);
 Molecule b = createMolecule(&quot;irgendwas&quot;);
 // tu was mit a und b---
 return 0;
}
</code></pre>
<p>Wenn ich das ausführe bekomme ich ganz einfach Speicherzugriffsfehler.<br />
Das liegt höchstwahrscheinlich an den Zeigern, die ich speichere.<br />
Ich sehe im Moment aber noch nicht die ganze Ursache, vermute aber irgendwelche<br />
Kopierereien und Zeiger auf nicht-mehr-gültige Objekte.</p>
<p>Kann mir jmd sagen, was ich falsch mache und wie ich das besser hinbekomme?</p>
<p>Eine konkrete Frage wäre auch, ob std::list&lt;Type&gt;.push_back( const Referenz auf Type) eine Kopie einfügt oder nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2183467</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183467</guid><dc:creator><![CDATA[shisha]]></dc:creator><pubDate>Mon, 20 Feb 2012 14:33:43 GMT</pubDate></item><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 15:36:20 GMT]]></title><description><![CDATA[<p>In createMolecule() fügst du einen Zeiger auf das LOKALE Atom a und b ein. Nach dem verlassen dieser Funktion ist der Zeiger ungültig. Warum benutzt du Zeiger?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2183494</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183494</guid><dc:creator><![CDATA[pyhax]]></dc:creator><pubDate>Mon, 20 Feb 2012 15:36:20 GMT</pubDate></item><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 15:42:53 GMT]]></title><description><![CDATA[<p>Das Problem liegt darin, dass du die Adresse von Elementen in einem Vektor benutzt. Wenn sich die Größe des Vektors ändert wird neuer Speicher allokiert und damit stimmen deine bisherigen Zeiger nicht mehr. Dazu gibt es mehrere Lösungsansätze:</p>
<ol>
<li>
<p>Globale Verwaltung von Atomen und Molekülen, die dynamisch erzeugt und in einem Pool erzeugt werden. Der Pool ist hinterher für die korrekte Freigabe der Objekte verantwortlich.</p>
</li>
<li>
<p>Identifikation der Atome und Moleküle per ID, statt Zeiger merkst du dir nur die ID der Atome/Moleküle. Wo sie sich im Speicher befinden ist dann egal, du brauchst nur wieder einen Pool, der dir die passenden Objekte zu einer ID zurückgibt.</p>
</li>
<li>
<p>Verwendung von smart_ptr. smart_ptr benutzen einen Referenzzähler und geben die Pointees automatisch frei, wenn der Referenzzähler 0 erreicht.</p>
</li>
</ol>
]]></description><link>https://www.c-plusplus.net/forum/post/2183496</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183496</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Mon, 20 Feb 2012 15:42:53 GMT</pubDate></item><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 16:28:02 GMT]]></title><description><![CDATA[<blockquote>
<ol start="3">
<li>Verwendung von smart_ptr. smart_ptr benutzen einen Referenzzähler und geben die Pointees automatisch frei, wenn der Referenzzähler 0 erreicht.</li>
</ol>
</blockquote>
<p>Mir käme jetzt nur shared_ptr in den Sinn. Allerdings weiß ich nicht ob das dem entspricht was ich möchte.</p>
<p>Solche smart Pointer habe ich bisher nur für mit new erzeugte Objekte gesehen.<br />
Für mich wäre allerdings wichtig, dass die Zeiger auch auf andere Objekte zeigen können und kein delete aufgerufen wird.</p>
<pre><code class="language-cpp">{
  Atom a;
  Atom b;
  a.connect(b);
  // a sollte nun die adresse von b kennen und umgekehrt
}
</code></pre>
<blockquote>
<p>Identifikation der Atome und Moleküle per ID, statt Zeiger merkst du dir nur die ID der Atome/Moleküle. Wo sie sich im Speicher befinden ist dann egal, du brauchst nur wieder einen Pool, der dir die passenden Objekte zu einer ID zurückgibt.</p>
</blockquote>
<p>Das hatte ich auch schon im Sinn, allerdings finde ich es recht mühsam und umständlich.</p>
<p>Sollte das ganze eventuell funktionieren, wenn ich noch den Copy-Ctr und Zuweisungsoperator überschreibe, so dass beim Umkopieren automatisch die neuen Adressen verwendet werden und im Zuge des DeCtr die Disconnects aufgerufen werden?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2183508</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183508</guid><dc:creator><![CDATA[shisha]]></dc:creator><pubDate>Mon, 20 Feb 2012 16:28:02 GMT</pubDate></item><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 16:40:47 GMT]]></title><description><![CDATA[<p>Ich dachte dabei eher an sowas:</p>
<pre><code class="language-cpp">class Pool
{
   std::vector&lt;Atom*&gt; Atoms_;

public:
   ~Pool()
   {
      for( std::vector&lt;Atom*&gt;::iterator it = Atoms_.begin(); it != Atoms_.end(); ++it )
      {
         delete **it;
      }
   }

   Atom&amp; acquire_atom()
   {
      Atoms_.push_back( new Atom() );
      return *Atoms_.back();
   }
};

int main()
{
   Pool p;
   Atom&amp; a = p.acquire_atom();
   Atom&amp; b = p.acquire_atom();

   a.connect( b );
}
</code></pre>
<p>Kannst dir jetzt natürlich noch was einfallen lassen, um nicht mehr benötigte Atome zu recyclen. Alle Atome haben jetzt die Lebenszeit des Pools, und da sie auf dem Heap erzeugt werden ändert sich ihre Adresse auch nie. Damit kannst du gefahrlos Zeiger benutzen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2183514</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183514</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Mon, 20 Feb 2012 16:40:47 GMT</pubDate></item><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 16:42:02 GMT]]></title><description><![CDATA[<p>Das ganze noch mit unique_ptr kombinieren und die Lösung ist nochmal besser <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2183516</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183516</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Mon, 20 Feb 2012 16:42:02 GMT</pubDate></item><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 16:45:30 GMT]]></title><description><![CDATA[<p>Habe hier kein C++11, kenn mich mit dem neumodischen Krams nicht aus <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>PS:<br />
War das so eine Art Lob? Von Pi? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2183517</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183517</guid><dc:creator><![CDATA[DocShoe]]></dc:creator><pubDate>Mon, 20 Feb 2012 16:45:30 GMT</pubDate></item><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 16:49:18 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">class Pool
{
   std::vector&lt;std::unique_ptr&lt;Atom&gt;&gt; Atoms_;

public:
   Atom&amp; acquire_atom()
   {
      Atoms_.push_back(std::unique_ptr&lt;Atom&gt;(new Atom()));
      return *Atoms_.back();
   }
};

int main()
{
   Pool p;
   Atom&amp; a = p.acquire_atom();
   Atom&amp; b = p.acquire_atom();

   a.connect( b );
}
</code></pre>
<p>Mal unique_ptr reingesteckt. Hat zusätzlich noch den Vorteil, dass der Compiler keinen in diesem Fall gefärlichen Copy Ctor und Copy operator = generiert.</p>
<p>Das war eine Art &quot;Noch bevor ich deinen Post gelesen habe, habe ich daran gedacht, es auch so vorzuschlagen.&quot;.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2183522</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183522</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Mon, 20 Feb 2012 16:49:18 GMT</pubDate></item><item><title><![CDATA[Reply to [Anfängerproblem] Zeiger&#x2F;Referenzen und Gültigkeitsbereiche on Mon, 20 Feb 2012 17:20:49 GMT]]></title><description><![CDATA[<p>Nochmal für den nicht ganz so Weisen. Ich habe Kopier-Konstruktor und Zuweisungskonstruktor hinzugefügt, so wie ich es mir mal vorgestellt habe.<br />
Das klappt immer noch nicht, aber ich weiß nicht an welcher Stelle mein Code genau crasht.<br />
Ändert sich ein Vector, ruft er ja für jedes Element den Kopierkonstruktor auf.<br />
In dem Kopierkonstruktor sollte mein meues Element ja dann die neue Adresse kennen, oder?</p>
<pre><code class="language-cpp">Atom::Atom()
{
    // TODO Auto-generated constructor stub

}

Atom::Atom(const Atom&amp; other)
{
    std::cout &lt;&lt; &quot;KOPIERKTR&quot; &lt;&lt; std::endl;
    x = other.x;
    y = other.y;
    z = other.z;

    for (std::list&lt;Atom*&gt;::const_iterator iter = other.neighbours.begin();
            iter != other.neighbours.end(); iter++)
    {
        connect(**iter);
    }
}

Atom&amp; Atom::operator=(const Atom&amp; other)
{
    if (this != &amp;other)
    {
        x = other.x;
        y = other.y;
        z = other.z;

        for (std::list&lt;Atom*&gt;::const_iterator iter = other.neighbours.begin();
                iter != other.neighbours.end(); iter++)
        {
            connect(**iter);
        }
    }
    return *this;
}

Atom::~Atom()
{
    for (std::list&lt;Atom*&gt;::iterator iter = neighbours.begin();
            iter != neighbours.end(); iter++)
    {
        disconnect(**iter);
    }
}
</code></pre>
<p>Ich habe versucht mir das mal aufzumalen:</p>
<pre><code>Atom A , Adresse 1
Atom B , Adresse 2

connect (A,B )=&gt;  A&lt;2&gt;  , B&lt;1&gt;.

Nun kommt ein Kopiervorgang:
A´ = Kopie von A.
A´ , Adresse 3
durch Kopierkonstruktor A´&lt;2&gt;  übernimmt die alte Adresse von B, B&lt;1,3&gt;
B hat nun das alte und neue A

A wird nun gelöscht:
B&lt;3&gt; hat nun nur noch Adresse von A´

B´ = Kopie(B) 
B´ Adresse 4
B´&lt;3&gt; kennt Adresse von neuem A´
A´&lt;2,4&gt;

B wird gelöscht:
A´ hat nun nur noch B´  &lt;4&gt;

und alle sollten glücklich sein...
zumindest nach dem Märchen
</code></pre>
<p>Wäre nett , wenn mir jmd meinem Denkfehler aufzeigen kann.</p>
<p>Falls ich nun doch eine Pool-Implementierung brauche, kann ich damit auch verschiedene Unterklassen von Atom problemfrei speichern?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2183536</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2183536</guid><dc:creator><![CDATA[shisha]]></dc:creator><pubDate>Mon, 20 Feb 2012 17:20:49 GMT</pubDate></item></channel></rss>