<?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[Move-Konstruktor Aufruf durch std::list]]></title><description><![CDATA[<p>Einen wunderschönen guten Morgen wünsche ich.<br />
Leider wird dieser getrübt durch ein kleines Problemchen ;-). Ich möchte eine std::list anlegen, welche als Container für eine Klasse herhalten soll, die eine Ressource hält. Da diese Ressource im Destruktor dieser Klasse wieder freigegeben werden muss, kann ich mir keinen - inperformanten - Copy-Konstruktor leisten.</p>
<pre><code class="language-cpp">#include &lt;list&gt;

class Class
{
private:
	void* m_memory;

public:
	Class(size_t size)  : m_memory(new char[size]) {}
	Class(Class&amp;&amp; move) : m_memory(move.m_memory) {
		move.m_memory = nullptr;
	} 
	~Class()
	{
		if( m_memory ) {
			delete this-&gt;m_memory;
		}
	}
};

int main()
{
	std::list&lt;Class&gt; l;
	l.push_back(Class(10));   // 1. Call: Class::Class(size_t)
	                          // 2. Call: Class::~Class()

	return 0;
}
</code></pre>
<p>Ein ganz simples Beispiel. Ich würde mir wünschen, dass der Move-Konstruktor durch std::list&lt;Class&gt;::push_back() aufgerufen wird. Die Methode ist überladen:</p>
<pre><code class="language-cpp">std::list&lt;Class&gt;::push_back(Class const&amp;);
std::list&lt;Class&gt;::push_back(Class&amp;&amp;);
</code></pre>
<p>Was genau mache ich falsch? Als Resultat erhalte ich Objekte in meiner std::list, welche ungültigen Speicher referenzieren.<br />
Die Alternative wäre folgende Deklaration:</p>
<pre><code class="language-cpp">std::list&lt;Class*&gt; l;
l.push_back(new Class(10));
</code></pre>
<p>Hier wird natürlich kein Destruktor aufgerufen, da es sich hier um kein temporäres Objekt handelt.<br />
Ich halte diese Variante jedoch für ziemlichen Unsinn, da die Liste intern sowieso ihre &quot;Nodes&quot; durch den std::allocator&lt;Class&gt; - respektive einem eigenen STL-Allokator - allokiert.</p>
<p>Für Hilfe wäre ich wirklich sehr dankbar.</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/272397/move-konstruktor-aufruf-durch-std-list</link><generator>RSS for Node</generator><lastBuildDate>Fri, 28 Aug 2026 22:11:54 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/272397.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 17 Aug 2010 05:55:57 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Move-Konstruktor Aufruf durch std::list on Tue, 17 Aug 2010 05:57:59 GMT]]></title><description><![CDATA[<p>Einen wunderschönen guten Morgen wünsche ich.<br />
Leider wird dieser getrübt durch ein kleines Problemchen ;-). Ich möchte eine std::list anlegen, welche als Container für eine Klasse herhalten soll, die eine Ressource hält. Da diese Ressource im Destruktor dieser Klasse wieder freigegeben werden muss, kann ich mir keinen - inperformanten - Copy-Konstruktor leisten.</p>
<pre><code class="language-cpp">#include &lt;list&gt;

class Class
{
private:
	void* m_memory;

public:
	Class(size_t size)  : m_memory(new char[size]) {}
	Class(Class&amp;&amp; move) : m_memory(move.m_memory) {
		move.m_memory = nullptr;
	} 
	~Class()
	{
		if( m_memory ) {
			delete this-&gt;m_memory;
		}
	}
};

int main()
{
	std::list&lt;Class&gt; l;
	l.push_back(Class(10));   // 1. Call: Class::Class(size_t)
	                          // 2. Call: Class::~Class()

	return 0;
}
</code></pre>
<p>Ein ganz simples Beispiel. Ich würde mir wünschen, dass der Move-Konstruktor durch std::list&lt;Class&gt;::push_back() aufgerufen wird. Die Methode ist überladen:</p>
<pre><code class="language-cpp">std::list&lt;Class&gt;::push_back(Class const&amp;);
std::list&lt;Class&gt;::push_back(Class&amp;&amp;);
</code></pre>
<p>Was genau mache ich falsch? Als Resultat erhalte ich Objekte in meiner std::list, welche ungültigen Speicher referenzieren.<br />
Die Alternative wäre folgende Deklaration:</p>
<pre><code class="language-cpp">std::list&lt;Class*&gt; l;
l.push_back(new Class(10));
</code></pre>
<p>Hier wird natürlich kein Destruktor aufgerufen, da es sich hier um kein temporäres Objekt handelt.<br />
Ich halte diese Variante jedoch für ziemlichen Unsinn, da die Liste intern sowieso ihre &quot;Nodes&quot; durch den std::allocator&lt;Class&gt; - respektive einem eigenen STL-Allokator - allokiert.</p>
<p>Für Hilfe wäre ich wirklich sehr dankbar.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1940813</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1940813</guid><dc:creator><![CDATA[FrEEzE2046]]></dc:creator><pubDate>Tue, 17 Aug 2010 05:57:59 GMT</pubDate></item><item><title><![CDATA[Reply to Move-Konstruktor Aufruf durch std::list on Tue, 17 Aug 2010 06:07:10 GMT]]></title><description><![CDATA[<p>Mach mal Zuweisungsoperator und Kopierkonstruktor private.<br />
Ansonsten müßte das klappen.<br />
Vielleicht gibt es ein emplace_back, das die &amp;&amp;-Überladung von push_back mit einem eigenen Namen ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1940815</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1940815</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Tue, 17 Aug 2010 06:07:10 GMT</pubDate></item><item><title><![CDATA[Reply to Move-Konstruktor Aufruf durch std::list on Tue, 17 Aug 2010 07:29:51 GMT]]></title><description><![CDATA[<p>Also...</p>
<ul>
<li>Je nach Version des Compilers, wird er entweder einen eigenen Kopierkonstruktor generieren oder nicht. Das solltest Du ausschließen. Die <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3053.html" rel="nofollow">aktuellsten Regeln</a> würden das verhindern. Aber Dein Compiler hält sich wahrscheinlich noch an ältere Regeln.</li>
<li>Du hast vergessen, Dich um Zuweisungsoperatoren zu kümmern</li>
<li>Du paarst <code>new[]</code> für ein char-Array mit <code>delete</code> auf void*. Pfui.</li>
<li>Du kannst Dir die Klasse sparen; denn dafür ist unique_ptr da</li>
</ul>
<pre><code class="language-cpp">#include &lt;cstddef&gt;
#include &lt;iostream&gt;
#include &lt;ostream&gt;
#include &lt;memory&gt;
#include &lt;list&gt;

using namespace std;

unique_ptr&lt;char[]&gt; make_char_array(std::size_t elements)
{
  unique_ptr&lt;char[]&gt; p (new char[elements]);
  return p;
}

int main() {
  list&lt;unique_ptr&lt;char[]&gt;&gt; l;
  l.push_back(make_char_array(10));
  l.front()[0] = 'x';
  l.front()[1] = '\0';
  cout &lt;&lt; l.front().get() &lt;&lt; endl;
}
</code></pre>
<p>Alternativ kannst Du einfach einen vector&lt;char&gt; benutzen. Der verhält sich eigentlich ähnlich und bietet darüber hinaus weitere Features an: Iteratoren, kann vergrößert werden, kann kopiert werden, kennt seine Größe. In C++0x werden Vektoren auch effizient &quot;movable&quot;. Das heißt, all das, was Du hier mit unique_ptr machen würdest, kannst Du genauso effizient auch mit vector&lt;char&gt; machen.</p>
<p>kk</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1940832</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1940832</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Tue, 17 Aug 2010 07:29:51 GMT</pubDate></item><item><title><![CDATA[Reply to Move-Konstruktor Aufruf durch std::list on Tue, 17 Aug 2010 08:33:30 GMT]]></title><description><![CDATA[<p>krümelkacker schrieb:</p>
<blockquote>
<p>Du paarst <code>new[]</code> für ein char-Array mit <code>delete</code> auf void*. Pfui.</p>
</blockquote>
<p>Danke für deine Antwort. Natürlich ist das nicht mein konkreter Anwendungsfall, sondern ein einfaches Beispiel. Mir ist klar, dass ein SmartPointer hier die richtige Wahl wäre, aber es ging doch einfach nur darum den Anwendungsfall zu demonstrieren.</p>
<p>Das ich hier nicht delete[] verwendet habe ist dem schnellen herunterschreiben dieses Beispiels geschuldet und nicht weiter ernst zu nehmen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1940865</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1940865</guid><dc:creator><![CDATA[FrEEzE2046]]></dc:creator><pubDate>Tue, 17 Aug 2010 08:33:30 GMT</pubDate></item></channel></rss>