<?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[1x Copy Konstruktor zu viel]]></title><description><![CDATA[<p>Nun, ich arbeite an einer einfache JSON-Library fuer <a href="http://ideone.com/ig82lR" rel="nofollow">http://ideone.com/ig82lR</a> (nicht erschrecken, Problem ist nicht minimal, <code>main</code> ist ganz unten ...).</p>
<p>Bei folgender Zeile wird 2x der Kopierkonstruktor aufgerufe, obwohl er nur einmal noetig sein sollte.</p>
<pre><code class="language-cpp">json::value v_arr = std::move(std::vector&lt;json::value&gt;{std::cref(v_str)});
</code></pre>
<p>Dieses Verhalten zeigt sich bei VS 2013 als auch bei gcc 4.7.2. Ich vermute, dass es mit der Initialisierungsliste zusammen haengt. Wenn das <code>std::cref</code> durch ein <code>std::move</code> ersetzt wird, dann wird nur immernoch einmal kopiert. Lasse ich es ganz weg, so wird 3x der Kopierkonstruktor aufgerufen.</p>
<p>Wie kann ich die eine ueberfluessige Kopie verhindern, bzw. woran liegt es?</p>
<p>Eine Loesung ist, eine separate Konstruktion des vectors:</p>
<pre><code class="language-cpp">std::vector&lt;json::value&gt; vals;
vals.emplace_back(v_str);
json::value v_arr = std::move(vals);
</code></pre>
<p>Ich habe durchdebuggt, aber Code der Standardbibliothek ist einfach nicht lesbar. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/topic/318327/1x-copy-konstruktor-zu-viel</link><generator>RSS for Node</generator><lastBuildDate>Mon, 27 Jul 2026 10:49:36 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/318327.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 08 Jul 2013 17:28:10 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Mon, 08 Jul 2013 17:33:24 GMT]]></title><description><![CDATA[<p>Nun, ich arbeite an einer einfache JSON-Library fuer <a href="http://ideone.com/ig82lR" rel="nofollow">http://ideone.com/ig82lR</a> (nicht erschrecken, Problem ist nicht minimal, <code>main</code> ist ganz unten ...).</p>
<p>Bei folgender Zeile wird 2x der Kopierkonstruktor aufgerufe, obwohl er nur einmal noetig sein sollte.</p>
<pre><code class="language-cpp">json::value v_arr = std::move(std::vector&lt;json::value&gt;{std::cref(v_str)});
</code></pre>
<p>Dieses Verhalten zeigt sich bei VS 2013 als auch bei gcc 4.7.2. Ich vermute, dass es mit der Initialisierungsliste zusammen haengt. Wenn das <code>std::cref</code> durch ein <code>std::move</code> ersetzt wird, dann wird nur immernoch einmal kopiert. Lasse ich es ganz weg, so wird 3x der Kopierkonstruktor aufgerufen.</p>
<p>Wie kann ich die eine ueberfluessige Kopie verhindern, bzw. woran liegt es?</p>
<p>Eine Loesung ist, eine separate Konstruktion des vectors:</p>
<pre><code class="language-cpp">std::vector&lt;json::value&gt; vals;
vals.emplace_back(v_str);
json::value v_arr = std::move(vals);
</code></pre>
<p>Ich habe durchdebuggt, aber Code der Standardbibliothek ist einfach nicht lesbar. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337505</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337505</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 08 Jul 2013 17:33:24 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Mon, 08 Jul 2013 18:33:09 GMT]]></title><description><![CDATA[<p>Hm, interessant. Sollte durchaus was mit der Initialisierungsliste zu tun haben, denn hier wird nur ein mal kopiert: <a href="http://ideone.com/4UviOJ" rel="nofollow">http://ideone.com/4UviOJ</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337540</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337540</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Mon, 08 Jul 2013 18:33:09 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Mon, 08 Jul 2013 18:44:08 GMT]]></title><description><![CDATA[<p>knivil schrieb:</p>
<blockquote>
<pre><code class="language-cpp">json::value v_arr = std::move(std::vector&lt;json::value&gt;{std::cref(v_str)});
</code></pre>
</blockquote>
<p>Das move da ist überflüssig.</p>
<p>Der Initialisierungslisten-Konstruktor von vector will initializer_list&lt;value&gt; haben, also erzeugt er aus deiner cref ein temporäres value objekt, gibt das an den konstruktor weiter und der kopiert das dann nochmal. Kommt das so hin?</p>
<p>dieser initializer_list-Kram ist nicht gerade move-freundlich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337544</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337544</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Mon, 08 Jul 2013 18:44:08 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Mon, 08 Jul 2013 19:45:58 GMT]]></title><description><![CDATA[<p><a href="http://en.cppreference.com/w/cpp/utility/initializer_list" rel="nofollow">http://en.cppreference.com/w/cpp/utility/initializer_list</a></p>
<p><code>std::initializer_list::iterator</code> ist <code>const T*</code> , also Move-blockend.<br />
Kann nicht gehen würd ich sagen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337548</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337548</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 08 Jul 2013 19:45:58 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Mon, 08 Jul 2013 20:19:35 GMT]]></title><description><![CDATA[<p>hustbaer schrieb:</p>
<blockquote>
<p><a href="http://en.cppreference.com/w/cpp/utility/initializer_list" rel="nofollow">http://en.cppreference.com/w/cpp/utility/initializer_list</a></p>
<p><code>std::initializer_list::iterator</code> ist <code>const T*</code> , also Move-blockend.<br />
Kann nicht gehen würd ich sagen.</p>
</blockquote>
<p>Ich moechte das Element von vector nicht moven, es sollte einmal in den vector kopiert werden. Er wird aber insgesamt 2x kopiert. Ausgabe:</p>
<pre><code class="language-cpp">move constructor string
copy constructor value
copy constructor value
move constructor array
</code></pre>
<p>Knackpunkt ist wahrscheinlich:</p>
<blockquote>
<p>The storage for std::initializer_list is unspecified (i.e. it could be automatic, temporary, or static read-only memory, depending on the situation).</p>
</blockquote>
<blockquote>
<p>Kommt das so hin?</p>
</blockquote>
<p>Ja, vielleicht <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Ich mag Initialisierungslisten nicht mehr ...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337570</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337570</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 08 Jul 2013 20:19:35 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Mon, 08 Jul 2013 22:43:14 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/21632">@knivil</a><br />
Hmmmmmmm, ja.<br />
Pfuh.<br />
*grübel*</p>
<p>Da müsste ich jetzt im Standard nachlesen. Hab mich nicht wirklich genau mit <code>std::initializer_list</code> beschäftigt.<br />
Ich habe halt das...</p>
<p><a href="http://cppreference.com" rel="nofollow">cppreference.com</a> schrieb:</p>
<blockquote>
<p>Initializer lists may be implemented as a pair of pointers or pointer and length. Copying a std::initializer_list does not copy the underlying objects. The underlying array is not guaranteed to exist after the lifetime of the original initializer list object has ended</p>
</blockquote>
<p>...so verstanden dass das &quot;original initializer list object&quot; schon eine Kopie der Objekte enthalten muss, nicht bloss z.B. ein Array aus Zeigern auf die Elemente die innerhalb der {} stehen.</p>
<p>Wenn diese Interpretation richtig ist, dann ist klar dass 2x kopiert werden muss. Eine Kopie rein in die initializer list, und wegen des <code>const T*</code> Iterators nochmal eine Kopie von der initializer list in den Vektor.</p>
<p>Und dein Versuch mit <code>cref</code> funktioniert nicht, weil der initializer list ctor von <code>std::vector&lt;T&gt;</code> eben nur eine <code>std::initializer_list&lt;T&gt;</code> annimmt, und keine <code>std::initializer_list&lt;T const&amp;&gt;</code> , was ja krümelkacker schon geschrieben hat.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337586</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337586</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 08 Jul 2013 22:43:14 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Mon, 08 Jul 2013 23:10:56 GMT]]></title><description><![CDATA[<p>wie wäre es mit</p>
<pre><code class="language-cpp">json::value v_arr = std::vector&lt;json::value&gt;(1,v_str);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2337588</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337588</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 08 Jul 2013 23:10:56 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Mon, 08 Jul 2013 23:39:02 GMT]]></title><description><![CDATA[<p>Hat cooky451 schon vorgeschlagen, bloss halt hinter nem Link versteckt <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/2337591</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337591</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 08 Jul 2013 23:39:02 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Tue, 09 Jul 2013 07:27:51 GMT]]></title><description><![CDATA[<p>Habt ihr den Standard nicht gelesen?</p>
<p>§8.5.4/5 schrieb:</p>
<blockquote>
<p>An object of type std::initializer_list&lt;E&gt; is constructed from an initializer list as if the implementation allocated an array of N elements of type E, where N is the number of elements in the initializer list.<br />
<strong>Each element of that array is copy-initialized with the corresponding element of the initializer list</strong>, and the <code>std::initializer_list&lt;E&gt;</code> object is constructed to refer to that array.</p>
</blockquote>
<p>Prinzipiell lässt sich das Problem auf <a href="http://ideone.com/bMkth9" rel="nofollow">http://ideone.com/bMkth9</a> reduzieren. Wie man sieht, wird zweimal Kopiert. Wieso? Einmal wird a für die <code>initializer_list</code> kopiert, und dann wird die Kopie noch einmal Kopiert, denn der <code>initializer_list</code> -Konstruktor von <code>vector</code> ist ja definiert als...</p>
<p>Table 100 — Sequence container requirements schrieb:</p>
<blockquote>
<p>X(il); Equivalent to X(il.begin(), il.end())</p>
</blockquote>
]]></description><link>https://www.c-plusplus.net/forum/post/2337611</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337611</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Tue, 09 Jul 2013 07:27:51 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Tue, 09 Jul 2013 07:52:22 GMT]]></title><description><![CDATA[<blockquote>
<p>Habt ihr den Standard nicht gelesen?</p>
</blockquote>
<p>Nein. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Danke fuer eure Muehen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337616</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337616</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Tue, 09 Jul 2013 07:52:22 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Tue, 09 Jul 2013 11:18:49 GMT]]></title><description><![CDATA[<p>Sone schrieb:</p>
<blockquote>
<blockquote>
<p><strong>Each element of that array is copy-initialized with the corresponding element of the initializer list</strong>, and the <code>std::initializer_list&lt;E&gt;</code> object is constructed to refer to that array.</p>
</blockquote>
</blockquote>
<p>Nur, um sicher zu gehen, dass das keiner falsch versteht: Kopier-Initialisierung impliziert keine Kopie. Das kann auch ein Move sein oder ganz wegoptimiert werden. Kopierinitialisierung ist auch das, was bei der Initialisierung von Funktionsparametern oder dem hier stattfindet:</p>
<pre><code class="language-cpp">unique_ptr&lt;int&gt; foo();

int main() {
  unique_ptr&lt;int&gt; bar = foo();  // Kopierinitialisierung
  double x = 23;                // Kopierinitialisierung
  double&amp; r = x;                // Kopierinitialisierung
}
</code></pre>
<p>Das heißt einfach so, wobei im ersten Fall hier höchstens &quot;gemoved&quot; wird (wenn die Move-Konstruktion nicht gerade wegoptimiert wird) und im zweiten Fall im wesentlichen nur implizit ein int in ein double umgewandelt wird und im dritten Fall nur die Referenz initialisiert wird. Dem gegenüber steht die <em>Direktinitialisierung</em>:</p>
<pre><code class="language-cpp">unique_ptr&lt;int&gt; foo();

int main() {
  unique_ptr&lt;int&gt; bar (foo());  // Direktinitialisierung
  double x (23);                // Direktinitialisierung
  double&amp; r (x);                // Direktinitialisierung
}
</code></pre>
<p>Der Unterschied dürfte auch bekannt sein: Bei der Kopierinitialisierung können nur Konstruktoren verwendet werden, die sich auch mit einem Parameter aufrufen lassen und nicht als <code>explicit</code> mariert wurden. Ob da jetzt was kopiert wird oder Peng, ist völlig egal.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337646</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337646</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Tue, 09 Jul 2013 11:18:49 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Tue, 09 Jul 2013 13:31:13 GMT]]></title><description><![CDATA[<p>Sone schrieb:</p>
<blockquote>
<p>Habt ihr den Standard nicht gelesen?</p>
</blockquote>
<p>Nein, hab' ich nicht. Geht das aus meinem Beitrag nicht hervor dass ich das nicht habe <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f921.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--clown_face"
      title=":clown:"
      alt="🤡"
    /><br />
Aber ich hab' wenigstens richtig vermutet, das reicht mir. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337678</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337678</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 09 Jul 2013 13:31:13 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Tue, 09 Jul 2013 13:47:15 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/24868">@krümelkacker</a><br />
Also erstmal meine ich dass der Standard genauestens alle Stellen beschreibt wo copy-elision erlaubt ist. Und alles was nicht erlaubt ist ist verboten.</p>
<p>Und zweitens... da steht dass es sich um ein Array handelt, und ich behaupte mal dass ein Array aus T und nicht ein Array aus T* gemeint ist.</p>
<p>Und wenn das Ding das kopiert wird ne LValue ist, dann bleibt halt nix anderes übrig als eine echte Kopie zu machen.<br />
Dass er ne RValue reinmoven könnte ist klar, aber in dem Beispiel ist's halt keine RValue.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337682</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337682</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 09 Jul 2013 13:47:15 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Tue, 09 Jul 2013 14:03:42 GMT]]></title><description><![CDATA[<p>Habe ich das nun richtig verstanden: Das Element wird in die Init-Liste reinkopiert und dann wird die Init-Liste in den Vector kopiert?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337688</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337688</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Tue, 09 Jul 2013 14:03:42 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Tue, 09 Jul 2013 14:10:15 GMT]]></title><description><![CDATA[<p>knivil schrieb:</p>
<blockquote>
<p>Habe ich das nun richtig verstanden: Das Element wird in die Init-Liste reinkopiert und dann wird die Init-Liste in den Vector kopiert?</p>
</blockquote>
<p>Korrekt, d.h. das Element, das in der Init-Liste steckt, wird kopiert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337691</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337691</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Tue, 09 Jul 2013 14:10:15 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Tue, 09 Jul 2013 14:35:25 GMT]]></title><description><![CDATA[<blockquote>
<p>Kopier-Initialisierung impliziert keine Kopie.</p>
</blockquote>
<p>Hat das jemand gesagt?</p>
<blockquote>
<p>If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered.<br />
The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3).</p>
</blockquote>
<p>Es kann und wird dann also per nicht-explizitem Move-Konstruktor gemoved werden, wenn</p>
<ul>
<li>Ein &quot;applikabler&quot; Move-Konstruktor definiert ist (also kein explizit oder implizit als deleted definierter).</li>
<li>Der Initializer-Ausdruck ein <em>rvalue</em>* oder ein <em>function lvalue</em> ist.</li>
</ul>
<p>*Also ein <em>xvalue</em> oder <em>prvalue</em></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337696</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337696</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Tue, 09 Jul 2013 14:35:25 GMT</pubDate></item><item><title><![CDATA[Reply to 1x Copy Konstruktor zu viel on Wed, 10 Jul 2013 08:20:24 GMT]]></title><description><![CDATA[<p>Sone schrieb:</p>
<blockquote>
<blockquote>
<p>Kopier-Initialisierung impliziert keine Kopie.</p>
</blockquote>
<p>Hat das jemand gesagt?</p>
</blockquote>
<p>Ich habe auch nicht behauptet oder implizieren wollen, dass du oder jemand das gesagt hätte. Das hätte man vielleicht an meiner Einleutung erkennen können, die du nicht zitiert hast.</p>
<p>hustbaer schrieb:</p>
<blockquote>
<p>...<br />
Und wenn das Ding das kopiert wird ne LValue ist, dann bleibt halt nix anderes übrig als eine echte Kopie zu machen.<br />
Dass er ne RValue reinmoven könnte ist klar, aber in dem Beispiel ist's halt keine RValue.</p>
</blockquote>
<p>Naja, std::cref(sonstwas) ist schon ein Rvalue-Ausdruck. Aber stimmt, eine Move-Konstruktion eines value-Objekts bei so einem Initialisierer kann und sollte man natürlich nicht erwarten. Und ich hoffe mal, dass das auch nicht so rübergekommen ist, als würde ich etwas anderes behaupten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2337849</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2337849</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 10 Jul 2013 08:20:24 GMT</pubDate></item></channel></rss>