arrays überladen



  • alterbro schrieb:

    jetzt hab ich mich gefragt ob das auch mit arrays funktioniert, um mir die schleifen zu ersparen.

    Das geht mit einem richtigen C++-Array ganz leicht:

    #include <array>
    
    int main()
    {
    	std::array<int, 123> arr;
    	arr.fill(9);
    }
    


  • tyrox:

    Danke

    sone:

    Eine schleife weniger= 0.5 sekunden gespart.

    in einem grossen projekt macht das was aus.


  • Mod

    alterbro schrieb:

    sone:

    Eine schleife weniger= 0.5 sekunden gespart.

    in einem grossen projekt macht das was aus.

    😮

    Denk mal darüber nach, was wohl im Computer passiert, wenn da keine Schleife zu sehen ist.

    edit: Tipp: Der genauen Formulierung meiner Aufforderung kann man schon die Lösung entnehmen.

    Jedenfalls hast du noch viel zu lernen, bevor du Performanceargumente bringen kannst, sonst wird das eher lustig (für andere).



  • TyRoXx schrieb:

    alterbro schrieb:

    jetzt hab ich mich gefragt ob das auch mit arrays funktioniert, um mir die schleifen zu ersparen.

    Das geht mit einem richtigen C++-Array ganz leicht:

    #include <array>
    
    int main()
    {
    	std::array<int, 123> arr;
    	arr.fill(9);
    }
    

    Das geht auch mit einem "normalen" C++ Array ganz leicht:

    #include <algorithm>
    
    int main()
    {
           int arr[123];
           std::fill(arr, arr + 123, 9);
    }
    


  • pyhax schrieb:

    Das geht auch mit einem "normalen" C++ Array ganz leicht

    Du meinst C-Array 😉

    Und ein Nachteil deiner Variante ist offensichtlich: Du gibst die Grösse nochmals an. Wenn man dann etwas mehr Funktionalität braucht, gehts erst recht nicht mehr so leicht (z.B. Kopieren, Zuweisen, Funktionsübergabe und -rückgabe). Ausserdem hat man keine Debug-Features wie Index- und Iteratorchecks, und die STL-Interfacekonformität ist auch nicht gegeben.

    std::array sollte man immer über rohe Arrays bevorzugen, für letztere spricht in C++ eigentlich nichts mehr. Leider werden sie doch noch oft verwendet.



  • Nexus schrieb:

    std::array sollte 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::array langsamer 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::array nicht 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::array nicht 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 werden
    

    Vielleicht 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 funktioniert

    template <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);
    

  • Mod

    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.


  • Mod

    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.


Anmelden zum Antworten