1x Copy Konstruktor zu viel
-
http://en.cppreference.com/w/cpp/utility/initializer_list
std::initializer_list::iteratoristconst T*, also Move-blockend.
Kann nicht gehen würd ich sagen.
-
hustbaer schrieb:
http://en.cppreference.com/w/cpp/utility/initializer_list
std::initializer_list::iteratoristconst T*, also Move-blockend.
Kann nicht gehen würd ich sagen.Ich moechte das Element von vector nicht moven, es sollte einmal in den vector kopiert werden. Er wird aber insgesamt 2x kopiert. Ausgabe:
move constructor string copy constructor value copy constructor value move constructor arrayKnackpunkt ist wahrscheinlich:
The storage for std::initializer_list is unspecified (i.e. it could be automatic, temporary, or static read-only memory, depending on the situation).
Kommt das so hin?
Ja, vielleicht

Ich mag Initialisierungslisten nicht mehr ...
-
@knivil
Hmmmmmmm, ja.
Pfuh.
*grübel*Da müsste ich jetzt im Standard nachlesen. Hab mich nicht wirklich genau mit
std::initializer_listbeschäftigt.
Ich habe halt das...cppreference.com schrieb:
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
...so verstanden dass das "original initializer list object" schon eine Kopie der Objekte enthalten muss, nicht bloss z.B. ein Array aus Zeigern auf die Elemente die innerhalb der {} stehen.
Wenn diese Interpretation richtig ist, dann ist klar dass 2x kopiert werden muss. Eine Kopie rein in die initializer list, und wegen des
const T*Iterators nochmal eine Kopie von der initializer list in den Vektor.Und dein Versuch mit
creffunktioniert nicht, weil der initializer list ctor vonstd::vector<T>eben nur einestd::initializer_list<T>annimmt, und keinestd::initializer_list<T const&>, was ja krümelkacker schon geschrieben hat.
-
wie wäre es mit
json::value v_arr = std::vector<json::value>(1,v_str);
-
Hat cooky451 schon vorgeschlagen, bloss halt hinter nem Link versteckt

-
Habt ihr den Standard nicht gelesen?
§8.5.4/5 schrieb:
An object of type std::initializer_list<E> 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.
Each element of that array is copy-initialized with the corresponding element of the initializer list, and thestd::initializer_list<E>object is constructed to refer to that array.Prinzipiell lässt sich das Problem auf http://ideone.com/bMkth9 reduzieren. Wie man sieht, wird zweimal Kopiert. Wieso? Einmal wird a für die
initializer_listkopiert, und dann wird die Kopie noch einmal Kopiert, denn derinitializer_list-Konstruktor vonvectorist ja definiert als...Table 100 — Sequence container requirements schrieb:
X(il); Equivalent to X(il.begin(), il.end())
-
Habt ihr den Standard nicht gelesen?
Nein.

Danke fuer eure Muehen.
-
Sone schrieb:
Each element of that array is copy-initialized with the corresponding element of the initializer list, and the
std::initializer_list<E>object is constructed to refer to that array.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:
unique_ptr<int> foo(); int main() { unique_ptr<int> bar = foo(); // Kopierinitialisierung double x = 23; // Kopierinitialisierung double& r = x; // Kopierinitialisierung }Das heißt einfach so, wobei im ersten Fall hier höchstens "gemoved" 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 Direktinitialisierung:
unique_ptr<int> foo(); int main() { unique_ptr<int> bar (foo()); // Direktinitialisierung double x (23); // Direktinitialisierung double& r (x); // Direktinitialisierung }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
explicitmariert wurden. Ob da jetzt was kopiert wird oder Peng, ist völlig egal.
-
Sone schrieb:
Habt ihr den Standard nicht gelesen?
Nein, hab' ich nicht. Geht das aus meinem Beitrag nicht hervor dass ich das nicht habe

Aber ich hab' wenigstens richtig vermutet, das reicht mir.
-
@krümelkacker
Also erstmal meine ich dass der Standard genauestens alle Stellen beschreibt wo copy-elision erlaubt ist. Und alles was nicht erlaubt ist ist verboten.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.
Und wenn das Ding das kopiert wird ne LValue ist, dann bleibt halt nix anderes übrig als eine echte Kopie zu machen.
Dass er ne RValue reinmoven könnte ist klar, aber in dem Beispiel ist's halt keine RValue.
-
Habe ich das nun richtig verstanden: Das Element wird in die Init-Liste reinkopiert und dann wird die Init-Liste in den Vector kopiert?
-
knivil schrieb:
Habe ich das nun richtig verstanden: Das Element wird in die Init-Liste reinkopiert und dann wird die Init-Liste in den Vector kopiert?
Korrekt, d.h. das Element, das in der Init-Liste steckt, wird kopiert.
-
Kopier-Initialisierung impliziert keine Kopie.
Hat das jemand gesagt?
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.
The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3).Es kann und wird dann also per nicht-explizitem Move-Konstruktor gemoved werden, wenn
- Ein "applikabler" Move-Konstruktor definiert ist (also kein explizit oder implizit als deleted definierter).
- Der Initializer-Ausdruck ein rvalue* oder ein function lvalue ist.
*Also ein xvalue oder prvalue
-
Sone schrieb:
Kopier-Initialisierung impliziert keine Kopie.
Hat das jemand gesagt?
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.
hustbaer schrieb:
...
Und wenn das Ding das kopiert wird ne LValue ist, dann bleibt halt nix anderes übrig als eine echte Kopie zu machen.
Dass er ne RValue reinmoven könnte ist klar, aber in dem Beispiel ist's halt keine RValue.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.