std::vector - resize() und reserve()
-
Verstehe. Danke!

-
Beispiel, wo reserve sinnvoll sein (kann): Wenn du nacheinander 50mal push_back aufrufst, wird der vector der Standardbibliothek im MSVC insgesamt elfmal (gcc: sieben mal) neuen Speicher besorgen. Dabei wird jedesmal der komplette Inhalt durch die Gegend kopiert, neuer Speicher angefordert und alter freigegeben...
In einem unserer Module hier auf Arbeit gibts eine Funktion, die neben einigen komplexeren Dingen einem Vector ein neues Element hinten anfügt. Diese Funktion wird von einer anderen Funktion oft aufgerufen, mit wechselnden Argumenten, wobei vorher die Zahl der Aufrufe immer bekannt ist. Durch Einsatz von reserve hab ich der aufrufenden Funktion 7% Laufzeit sparen können.
-
hi ihr,
hier ist ein Beispiel bei dem resize sinnvoll ist .. hat immer funktioniert in gcc4.0
std::vector< std::vector<myData> > mMy;
std::for_each( mMy.begin(), mMy.end(), std::bind2nd(std::mem_fun_ref(&std::vector< myData >::resize), numMy) );
in gcc4.2 geht das aber nicht mehr, weil resize jetzt anders funktioniert ..
hat einer von euch vielleicht einen plan was ich machen muss, um das obige Beispiel auf gcc4.2 compilieren zu können ?
grüsse,
bzt
-
std::for_each(v.begin(), v.end(), [n](std::vector<int> &i) { i.resize(n); });getestet mit GCC 4.7
-
bzt schrieb:
std::vector< std::vector<myData> > mMy;
std::for_each( mMy.begin(), mMy.end(), std::bind2nd(std::mem_fun_ref(&std::vector< myData >::resize), numMy) );
in gcc4.2 geht das aber nicht mehr, weil resize jetzt anders funktioniert ..
Was ist denn das Problem? Hat GCC 4.2 ne andere Signatur für vector::resize (vielleicht mit zusätzlichen Default-Parametern oder sowas)?
hat einer von euch vielleicht einen plan was ich machen muss, um das obige Beispiel auf gcc4.2 compilieren zu können ?
Entweder so wie rüdiger es vorgeschlagen hat oder eigene Wrapper-Funktion schreiben.
ps: oder BOOST_FOREACH verwenden oder den Loop "klassisch" mit Iteratoren/Index hinschreiben.
-
hustbaer schrieb:
bzt schrieb:
std::vector< std::vector<myData> > mMy;
std::for_each( mMy.begin(), mMy.end(), std::bind2nd(std::mem_fun_ref(&std::vector< myData >::resize), numMy) );
in gcc4.2 geht das aber nicht mehr, weil resize jetzt anders funktioniert ..
Was ist denn das Problem? Hat GCC 4.2 ne andere Signatur für vector::resize (vielleicht mit zusätzlichen Default-Parametern oder sowas)?
Es war noch nie garantiert, dass man Funktionszeiger auf Std-Container-Methoden benutzen kann.
-
ich verstehe Rüdigers Antwort nicht wirklich, denn seinen Vorschlag kann ich gar nicht compilieren .. bei mir fehlen da lauter primary expressions .. vielleicht kann Rüdiger das genauer erklären .. und bei gcc40 war resize überladen und mem_fun_ref hatte damit keine probleme .. und das wurde von den Gnu Jungs getreu dem standard geändert in gcc42 ..
-
bzt schrieb:
ich verstehe Rüdigers Antwort nicht wirklich, denn seinen Vorschlag kann ich gar nicht compilieren ..
Dazu brauchst du einen aktuellen GCC, der C++11 Lambdas unterstützt.
-
Bei
g++ 4.7muss noch-std=c++0xals Option mitgegeben werden.
-
ist leider nicht wirklich eine option gcc upzudaten, es wäre gut eine Lösung zu finden die auf gcc42 funktioniert ..
-
Dann schreibe einen Funktor!
-
TyRoXx schrieb:
hustbaer schrieb:
bzt schrieb:
std::vector< std::vector<myData> > mMy;
std::for_each( mMy.begin(), mMy.end(), std::bind2nd(std::mem_fun_ref(&std::vector< myData >::resize), numMy) );
in gcc4.2 geht das aber nicht mehr, weil resize jetzt anders funktioniert ..
Was ist denn das Problem? Hat GCC 4.2 ne andere Signatur für vector::resize (vielleicht mit zusätzlichen Default-Parametern oder sowas)?
Es war noch nie garantiert, dass man Funktionszeiger auf Std-Container-Methoden benutzen kann.
Das hab ich ja auch nicht behauptet (ganz absichtlich nicht, da ich nicht sicher bin/war ob die exakte Signatur der Memberfunktionen vorgeschrieben ist).
Und: meinst du es ist nicht garantiert weil die exakte Signatur nicht vorgeschrieben ist? Oder weil es irgendwie erlaubt ist Dinge wie std::vector mit "Compiler-Magick" zu implementieren, so dass man überhaupt gar keine Memberfunktionszeiger verwenden könnte, nichtmal wenn man die exakte Signatur der Funktion kennt bzw. den Memberfunktionszeiger-Typ über ein Template herleitet?
(Das würde mich nämlich einigermassen wundern, wäre aber nicht das erste mal dass mich der Standard verwundert *g*)Ich hab' allerdings hauptsächlich aus Interesse gefragt, denn anscheinend ist es mit GCC 4.0 ja noch gegangen, und mit 4.2 nimmer. Muss sich also was geändert haben, mich würde interessieren was (einfach nur so).
-
das kann ich dir genau sagen, weil ich die Gnu Jungs kontaktiert habe ..
I am fairly sure the problem is that a single resize member function
with this signature:void resize(size_type, const T& = T());
was replaced with a pair of overloaded functions with these signatures:
void resize(size_type);
void resize(size_type, const T&);This change is allowed by the standard, but means that
&vector<myData>::resize is no longer unambiguous.You can disambiguate the expression by providing a target type to
convert to, so the compiler knows which overload you mean:typedef void (*resize_type)(std::vector< myData >::size_type);
std::bind2nd(std::mem_fun_ref((resize_type)&std::vector< myData
::resize), numMyData) );
aber so richtig hilfreich ist das noch nicht, da ich nicht weiss wie ich dem compiler sage welchen overload er nutzen soll .. es ist wohl der zweite, aber ich verstehe auch nicht was const T& = T() bedeutet und ob es das gleiche ist wie const T& ?
-
hustbaer schrieb:
Und: meinst du es ist nicht garantiert weil die exakte Signatur nicht vorgeschrieben ist? Oder weil es irgendwie erlaubt ist Dinge wie std::vector mit "Compiler-Magick" zu implementieren, so dass man überhaupt gar keine Memberfunktionszeiger verwenden könnte, nichtmal wenn man die exakte Signatur der Funktion kennt bzw. den Memberfunktionszeiger-Typ über ein Template herleitet?
(Das würde mich nämlich einigermassen wundern, wäre aber nicht das erste mal dass mich der Standard verwundert *g*)Ich habe den Standard nicht gelesen, aber in vermute, dass zumindest die Implementation des Standardarguments von
resizeimplementationsabhängig ist.void resize(size_type); void resize(size_type, T); //ebenfalls legal: void resize(size_type, T = T());hustbaer schrieb:
Ich hab' allerdings hauptsächlich aus Interesse gefragt, denn anscheinend ist es mit GCC 4.0 ja noch gegangen, und mit 4.2 nimmer. Muss sich also was geändert haben, mich würde interessieren was (einfach nur so).
GCC hat vielleicht einfach von der zweiten auf die erste Variante gewechselt.
Das sind alles nur Spekulationen von mir. Ob das wirklich stimmt, ist aber unerheblich, weil man sich nicht auf die Signaturen von Standardmethoden verlassen sollte.
push_backhat mit C++11 auch eine Überladung bekommen.
-
C++11 schrieb:
17.6.5.5 Member functions [member.functions]
1 It is unspecified whether any member functions in the C ++ standard library are defined as inline (7.1.2).
2 An implementation may declare additional non-virtual member function signatures within a class:
— by adding arguments with default values to a member function signature;187 [ Note: An implementation may not add arguments with default values to virtual, global, or non-member functions. — end note ]
— by replacing a member function signature with default values by two or more member function signatures with equivalent behavior; and
— by adding a member function signature for a member function name.
3 A call to a member function signature described in the C ++ standard library behaves as if the implementation declares no additional member function signatures.