arrays überladen
-
Nexus schrieb:
std::arraysollte man immer über rohe Arrays bevorzugen, für letztere spricht in C++ eigentlich nichts mehr. Leider werden sie doch noch oft verwendet.Speed

Außerdem kann man die Größe eines (echten) C-Style Arrays ganz einfach bestimmen, und ich sehe auch überhaupt nicht ein, wozu man in kleinen Situationen gleich ein STL-Container braucht, wenn es auch ein C-Style Array tut.
-
Es gibt keinen Performaceunterschied zwischen normalen Arrays und std::array.
-
Sone schrieb:
Speed

Genau wegen solcher Irrtümer werden immer noch Arrays verwendet. Die Hälfte aller C++-Mythen existiert ohnehin nur wegen Unwissen im Bezug auf Performance, ist also nicht speziell verwunderlich.
Sag mir, warum
std::arraylangsamer als ein C-Array sein sollte. Im Release-Modus natürlich.Sone schrieb:
Außerdem kann man die Größe eines (echten) C-Style Arrays ganz einfach bestimmen
Ja, ganz einfach.
sizeof(array)/sizeof(array[0])Kommt es zum "array-to-pointer decay", hat man schöne Bugs. Übrigens ist diese Konvertierung auch so ein implizites "Feature", das man mit
std::arraynicht hat.Sone schrieb:
und ich sehe auch überhaupt nicht ein, wozu man in kleinen Situationen gleich ein STL-Container braucht, wenn es auch ein C-Style Array tut.
Umso besser, dass ich im letzten Post genügend Gründe genannt habe

-
Nexus schrieb:
Ja, ganz einfach.
sizeof(array)/sizeof(array[0])Kommt es zum "array-to-pointer decay", hat man schöne Bugs. Übrigens ist diese Konvertierung auch so ein implizites "Feature", das man mit
std::arraynicht hat.Ich kann dir nur zustimmen. Genau darüber bin ich letztens wieder gestolpert. Unter extremem Zeitdruck eine RS232-Kommunikations-Funktion zusammengecopypastet, dabei einige lokale Variablen zu Parametern gemacht und nicht die Längenbestimmung angepasst - und mich dann gewundert, dass immer nur 4 Bytes geschrieben werden.
Leute, nehmt einfach einen vernünftigen Container. Ihr erspart euch eventuell einiges an Ärger. Wenn ihr dann meint, dass der zu langsam ist und ihr ein echtes Zeitproblem habt (nicht, weil optimieren cool ist), dann könnt ihr es immer noch testweise umbauen und messen, ob es irgendwas bringt.
-
Da sowohl normale Arrays als auch std::array eine konstante Größe erfordern, ist es total egal wie gut man im Code die Größe bestimmen kann, da sie sowieso bekannt sein muss. "Magic numbers" als Arraygrößen sind sowieso Krebs und sollten durch etwas mit Namen ersetzt werdenn.
-
Der einzige Nachteil, den ich bei std::array kenne, ist, dass man die Größe immer angeben muss. Das kann bei einer Initialisierung unpraktisch sein. Z.B.
int data[] = { 1, 2, 3, 4, 5 }; // Größe deduziert arra<int, 5> = { 1, 2, 3, 4, 5 }; // Größe muss angegeben werdenVielleicht bietet C++1y ja eine Lösung hierfür.
-
Ethon schrieb:
Da sowohl normale Arrays als auch std::array eine konstante Größe erfordern, ist es total egal wie gut man im Code die Größe bestimmen kann, da sie sowieso bekannt sein muss.
Das ist aber leider nicht gegeben. Sobald ich das Array naemlich an eine Funktion uebergebe verliere ich idR diese Information. Ich kann natuerlich immer aufpassen die korrekte Groesse immer mitzugeben - aber bei std::array ist sie immer da egal was passiert.
std::array ist in jeder einzelnen Situation besser (bzw. gleich gut) als ein plain array. Jeder einzelnen.
PS:
@Kellerautomat:
du kannst dir ein make_array bauen mit variadic templates und auto als typ verwenden.PPS:
kann mir wer erklaeren warum folgendes funktionierttemplate <typename Head, typename... Tail> std::array<Head,1+sizeof...(Tail)> make_array(Head head, Tail const&... tail) { std::array<Head,1+sizeof...(Tail)> a={ head, tail... }; return a; }aber folgendes nicht?
template <typename Head, typename... Tail> std::array<Head,1+sizeof...(Tail)> make_array(Head head, Tail const&... tail) { return std::array<Head,1+sizeof...(Tail)> ({ head, tail... }); }
-
Kellerautomat schrieb:
Vielleicht bietet C++1y ja eine Lösung hierfür.
Oder C++11 mit einem selbstgeschriebenen Variadic Function Template
make_array(). Kenne mich leider mit Variadic Templates nicht aus.
-
Mein Vorschlag fuer make_array:
template <typename Head, typename... Tail> std::array<Head, 1+sizeof...(Tail)> make_array(Head&& head, Tail&&... tail) { return std::array<Head, 1+sizeof...(Tail)> { std::forward<Head>(head), std::forward<Tail>(tail)... }; }Verbesserungsvorschlaege willkommen
Bin mit den neuen features noch nicht so per du
-
Funktioniert mit Clang 3.0:
#include <array> template <class First, class ...Rest> auto make_array(First && first, Rest && ...rest) -> std::array<First, 1 + sizeof...(Rest)> { return { std::forward<First>(first), std::forward<Rest>(rest)... }; } int main() { const auto a = make_array(1, 2, 3, 4); static_assert(std::is_same<const std::array<int, 4>, decltype(a)>::value, "make_array liefert einen unerwarteten Typ"); }Ist das korrekt und optimal so?
-
Shade Of Mine schrieb:
Ethon schrieb:
Da sowohl normale Arrays als auch std::array eine konstante Größe erfordern, ist es total egal wie gut man im Code die Größe bestimmen kann, da sie sowieso bekannt sein muss.
Das ist aber leider nicht gegeben. Sobald ich das Array naemlich an eine Funktion uebergebe verliere ich idR diese Information. Ich kann natuerlich immer aufpassen die korrekte Groesse immer mitzugeben - aber bei std::array ist sie immer da egal was passiert.
std::array ist in jeder einzelnen Situation besser (bzw. gleich gut) als ein plain array. Jeder einzelnen.
Nö, bei std::array musst du die Information doch auch explizit mitgeben.
template<std::size_t Size> void i_like_ints(std::array<int, Size>& ints) {}
-
Ethon schrieb:
Nö, bei std::array musst du die Information doch auch explizit mitgeben.
Bei einem plain array musst du das nicht.

-
Ethon schrieb:
template<std::size_t Size> void i_like_ints(std::array<int, Size>& ints) {}Keine Ahnung warum man so ein template haben will, aber bitte - funktioniert einwandfrei:
auto a=make_array(1,2,3,4,5); i_like_ints(a);
-
Shade Of Mine schrieb:
aber folgendes nicht?
template <typename Head, typename... Tail> std::array<Head,1+sizeof...(Tail)> make_array(Head head, Tail const&... tail) { return std::array<Head,1+sizeof...(Tail)> ({ head, tail... }); }Weil hierfür ein list-Konstruktor erforderlich wäre.
-
Mein Vorschlag
template <typename... Args> constexpr std::array<typename std::common_type<typename std::decay<Args>::type...>::type, sizeof...(Args)> make_array(Args&&... args) { return { std::forward<Args>( args )... }; }evtl. noch eine Prüfung, dass kein narrowing stattfindet.
-
camper schrieb:
Weil hierfür ein list-Konstruktor erforderlich wäre.
Gibt es einen Grund warum es so einen ctor nicht gibt?
Klar kann man nicht statisch ueberpruefen dass die elementanzahl passt - aber das waere per assert ja auch ok...
-
Shade Of Mine schrieb:
Gibt es einen Grund warum es so einen ctor nicht gibt?
Weil array ein Aggregat sein soll. Wenn es keins wäre und ein List-Konstruktor existierte, hätte man u.a. auch das Problem, dass Narrowing verboten wäre; da array nichts Neues ist, hätte man dann auch mit zusätzlichen Inkompatibilitäten gegenüber C++03 zu kämpfen.
-
camper schrieb:
Shade Of Mine schrieb:
Gibt es einen Grund warum es so einen ctor nicht gibt?
Weil array ein Aggregat sein soll.
oh, ok.
macht natuerlich sinn.
-
Shade Of Mine schrieb:
camper schrieb:
Shade Of Mine schrieb:
Gibt es einen Grund warum es so einen ctor nicht gibt?
Weil array ein Aggregat sein soll.
oh, ok.
macht natuerlich sinn.Wenn man weiter denkt, eigentlich nicht.
array ist ja deshalb als Aggregat eingeführt worden, damit diese Art Initialisierung (auch in C++03) durchgeführt werden kann. Jetzt wäre das an sich nicht mehr erforderlich. Und weil es unterspezifiziert ist, kann man std::array nicht felxibel einsetzen, wenn man portabel bleiben will: es wird nämlich nicht gesagt, wie die vollständige Klammerung auszusehen hat, sondern nur, dassarray<T, N> a = { initializer-list };funktionieren soll. Dabei findet allerdings mit Sicherheit brace-elision statt, und gerade die ist ja in anderen Kontexten (z.B. Member-Initialisierer) nicht zulässig.
Nur steht eben nirgendwo, dassarray<T, N> a = {{ initializer-list }};a) möglich und b) die vollstäng geklammerte Variante ist.
Beispielsweise könnte array ja so aussehen
template <typename T, size_t N> struct array { ... T elems[1][1][1][N]; };unsinnig, aber möglich.