memcpy, memmove, calloc, memset in C++?



  • Um noch der Vollständigkeit wegen, die C++ Features zu zeigen:

    using std::tr1::array; // alternativ boost::array
    
    // 10er int-Array
    array<int,10> a = { { 1, 2, 3, 4, 5 } };
    
    // 4er String-Array
    array<std::string,4> seasons = {
            { "spring", "summer", "autumn", "winter" }
    };
    
    // 2D-Array mit Strings:
    array<array<std::string,4>,2> seasons_i18n = {
            { { { "spring", "summer", "autumn", "winter", } },
              { { "Fruehling", "Sommer", "Herbst", "Winter" } }
            }
    };
    
    // -------------------------------------
    typedef array<int, 4> my_array;
    
    my_array a1 = {{ 23 }};
    
    my_array a2(a1); // kopiert a1 in a2
    
    my_array a3;
    a3 = a1;   // kopier a1 in a3
    
    if( a1 == a2 )
      cout << "a1 und a2 gleicher Inhalt.";
    

    Tja, das ist C++. 😃


  • Administrator

    rüdiger schrieb:

    @Dravere
    Dein Ansatz ist bereits falsch. Du versuchst C in C++ zu programmieren. Das ist falsch. Vergiss C und programmier C++. In C++ benutzt man zB eher std::vector oder std::tr1::array, anstelle sich um die Speicherverwaltung zu kümmern. Wenn man dir nun sagt, das man mit new calloc ersetzen kannst, wirst du vermutlich weiterhin C in C++ programmieren, nur eben mit new anstelle calloc...

    Stimmt irgendwie schon ^^
    Aber trotzdem würde man halt manchmal gern, auch in C++ plötzlich ein memset machen oder sowas. Da wäre es angenehm, wenn man eben äquivalente Lösungen kennt 😉

    @Artchi,
    I love you ... eeeeh ... nein, also nicht wirklich ... aber vielen Dank 😃

    @vista,
    Auch danke 😉
    O..o Ich sage einem VISTA danke, meine Welt stürzt ein 😃

    Grüssli



  • Dravere schrieb:

    Aber trotzdem würde man halt manchmal gern, auch in C++ plötzlich ein memset machen oder sowas. Da wäre es angenehm, wenn man eben äquivalente Lösungen kennt 😉

    Warum ist das so? Weil du vorher C programmiert hast? Genau aus dem Grund ist es nicht gut, wenn man mit C anfängt, wenn man eigentlich C++ programmieren will.

    Ich habe z.B. in meinem Leben noch nie malloc, realloc oder so benutzt. Ich mußte gestern abend sogar wegen diesem Thread erstmal nachschauen was calloc() überhaupt ist! 🙄 Habe ich zum erstmal gehört.



  • Ich habe z.B. in meinem Leben noch nie malloc, realloc oder so benutzt. Ich mußte gestern abend sogar wegen diesem Thread erstmal nachschauen was calloc() überhaupt ist! Habe ich zum erstmal gehört.

    ...musste ich auch 🤡


  • Administrator

    Artchi schrieb:

    Dravere schrieb:

    Aber trotzdem würde man halt manchmal gern, auch in C++ plötzlich ein memset machen oder sowas. Da wäre es angenehm, wenn man eben äquivalente Lösungen kennt 😉

    Warum ist das so? Weil du vorher C programmiert hast?

    Nein, ich drücke mich daher mal anderst aus, vielleicht kommst dann dahinter, was ich gemeint habe:
    Es kommt manchmal vor, dass man einen Speicherbereich mit 0s füllen möchte.
    Da fragt man sich halt, wie man dies in C++ macht. Ich kenne da halt zufälligerweise das memset von C und würde dies verwenden, da ich bis anhin, dass std::fill nicht kannte. Jemand der bis anhin nur C++ programmiert hat, der kommt auch auf die Idee, dass er ein Array mit 0s füllen möchte, doch der kennt dann eben schon das std::fill.

    Verstanden? ^^

    Grüssli



  • Drave! Meine Frage war nicht schlecht gemeint. Wollte nur wissen, ob du C vorher gemacht hast, da viele gesagt bekommen, das man vorher C lernen soll (was natürlich nicht zu empfehlen ist). Egal, jedenfalls kann ich dir nur als Tip für die Zukunft geben: lerne die C++-Standardlibrary, dann wirst du hoffentlich bald vom C-Style weg kommen. Man muß die C++-Stdlib nicht auswendig lernen (Kann ich auch nicht), aber wenn man darüber gelesen hat wie sie arbeitet und deren Konzepte, und die Standard-Algorithmen (reverse, sort, fill, find usw.), wird man diese auch eher benutzen.

    Wie gesagt, es ist meine Empfehlung und kein Vorwurf.



  • Artchi schrieb:

    Um noch der Vollständigkeit wegen, die C++ Features zu zeigen:

    using std::tr1::array; // alternativ boost::array
    
    // 10er int-Array
    array<int,10> a = { { 1, 2, 3, 4, 5 } };
    
    // 4er String-Array
    array<std::string,4> seasons = {
            { "spring", "summer", "autumn", "winter" }
    };
    
    // 2D-Array mit Strings:
    array<array<std::string,4>,2> seasons_i18n = {
            { { { "spring", "summer", "autumn", "winter", } },
              { { "Fruehling", "Sommer", "Herbst", "Winter" } }
            }
    }
    

    Ein bisschen viele Geschweiften Klammern 🙂 Hätte man das nicht so machen können, dass man weniger Klammern benutzt, oder was steckt dahinter ?



  • Sorry, bei einfachen arrays (also 1D) kann man die "zuvielen" Klammern weg lassen:

    array<std::string,4> a = { "spring", "summer", "autumn", "winter" };
    

    Bei den 2D-Arrays müssen die vielen Klammern sein. Warum das so ist, kann ich leider nicht sagen. Ist aber halt alles mit Operatorüberladung gelöst und kein Core-C++-Feature. Ihr könnt das also mit aktuellen Compilern problemlos benutzen.

    C++2009 wird das ganze dann übrigens wohl auch für vector anbieten, mit der {}-Initialisierer.



  • Artchi schrieb:

    Ist aber halt alles mit Operatorüberladung gelöst und kein Core-C++-Feature.

    Ok, danke. Erklärt dann einiges 🙂


  • Administrator

    Artchi schrieb:

    Drave! Meine Frage war nicht schlecht gemeint. Wollte nur wissen, ob du C vorher gemacht hast, da viele gesagt bekommen, das man vorher C lernen soll (was natürlich nicht zu empfehlen ist).

    Hab es auch nicht unbedingt als Vorwurf aufgefasst, wollte nur meinen Standpunkt erklären. Um die Frage vielleicht noch direkt zu beantworten:
    Ich habe damals direkt mit der MFC angefangen. Das war ein Buch von der Mircosoft Press, zuerst gab es eine kurze Einführung über C++ und danach ging es gleich mit der MFC los. Allerdings über die Einführung, kann ich heute sagen, kann man sich sehr streiten. So werden dort (int)-Cast als C++ verkauft. static_cast usw. werden gar nicht erst erwähnt und so geht es dann auch weiter *g*
    Was die MFC betrifft, da war es allerdings perfekt ^^

    Zudem habe ich inzwischen ein C++-Buch gekauft, sogar von Stroustrup, allerdings hatte ich bisher noch keine Zeit damit anzufangen 😉

    Grüssli



  • Dravere schrieb:

    ...Es kommt manchmal vor, dass man einen Speicherbereich mit 0s füllen möchte...

    Wann passiert das ? Und warum ?
    Ich muss gestehen, dass bei mir so schnell nicht das Bedürfnis aufkommt, "einen Speicherberich mit Nullen zu füllen"...
    Ich kenne zwar aus C das Bestreben, einen "Objekte" zu initialisieren, aber dafür hat man in C++ Konstruktoren, die das viel besser erledigen.
    Ansonsten lösen "genullte Speicherbereiche" keine besonderen Glücksgefühle in mir aus. 😉

    Gruß,

    Simon2.



  • In C++ benutzt man zB eher std::vector oder std::tr1::array, anstelle sich um die Speicherverwaltung zu kümmern.

    Der grosse Nachteil von C++ ist aber, das die "c++ Schnittstellen" nicht standartiesiert sind. Sprich, willst du Programme mit anderen Modulen erweitern und dich nicht auf einen compiler (eine programmiersprache) festlegen, laesst dich C++ gnadenlos im Stich 😞
    Da werden Schnittstellen incompatibel zueinander zum Teil nur durch blosse compiler-parameter.

    Das wiederum heisst, bei modularer programmierung bist du auf C-Schnittstellen angeweisen.

    Das wiederum heisst, willst du da einigermassen performant bleiben (ueberfluessige kopien vermeiden) musst du das Spiel in C mitspielen.

    Ansonsten stimme ich zu, innerhalb geschlossener Programme sollt man in C++ den Biblos die speicherverwaltung ueberlassen, und nur notfalls mittels eigener Allokatoren da eingreifen.

    Ciao ...



  • RHBaum schrieb:

    ...
    Der grosse Nachteil von C++ ist aber, das die "c++ Schnittstellen" nicht standartiesiert sind. Sprich, willst du Programme mit anderen Modulen erweitern und dich nicht auf einen compiler (eine programmiersprache) festlegen, laesst dich C++ gnadenlos im Stich 😞
    Da werden Schnittstellen incompatibel zueinander zum Teil nur durch blosse compiler-parameter. ...

    Naja - aber nur, wenn man auf Link- oder Laufzeitebene ansetzt oder sich mit der Programmierung nicht an den Standard hält.
    Letztlich halte ich es auf jeden Fall für besser, erstmal "sauberes C++" zu programmieren und "im Fall des Falles" C-APIs an den entscheidenden Stellen zu stricken .... selten weiß man im Vorhinein, wo und wie man welche "Fremdmodule" dranpflanschen muss.

    Gruß,

    Simon2.



  • Naja - aber nur, wenn man auf Link- oder Laufzeitebene ansetzt

    Was meistens der Fall ist, wenn man den Compiler nicht vorschreiben will / kann

    Bei uns halt tiefgreifendes Problem. Wir schreiben Anwendungen, die durch Module erweitert werden koennen / müssen. Die Module schreiben teilweisse auch externe Firmen. Den wiederum kannst ned vorschreiben, was fuern compiler sie zu verwenden haben.

    Will damit ja nur sagen, dass man leider noch auf das gute alte C angewiesen ist, solange sich da bei der standartiesierung nix tut. Und denk mal das das nicht wenige praxisorientierte Projekte betrifft.

    Ciao ...



  • Wenn der Sourcecode nicht bereit gestellt wird, kann das tatsächlich zu einem Konflikt führen. Aber für den übernächsten C++-Standard wird hoffentlich eine Sharedlibrary-Spezifikation rauskommen. Zumindest ist das auf der Todo-Liste des Komitees. Dann müsste sich dieses "Problem" in Luft auflösen? Hoffe ich zumindest, das da Nägel mit Köpfen gemacht wird. Vielleicht wird auch CLI Einzug halten? Naja, solange müssen wir uns noch gedulden oder selber Proposals einreichen.


  • Administrator

    @Simon2,
    Konstruktor schön und gut, aber dort musst du dann trotzdem die Nullen reinsetzen ^^

    class ClassX
    {
    public:
        ClassX()
        { std::fill(m_IntegerArray, m_IntegerArray + 10, 0); }
    
    private:
        int m_IntegerArray[10];
        const static int m_nLength = 10;
    
    public:
        void display();
        void edit();
    }
    
    void ClassX::display()
    {
        for(int i = 0; i < m_nLength; ++i)
        { std::cout << m_IntegerArray[i] << " "; }
    
        std::cout << std::endl << std::endl;
    }
    
    void ClassX::edit()
    {
        display();
    
        // Und dann das editieren ^^
    }
    

    Wenn die Grösse konstant ist, wirst du ja wohl nicht einen Vektor nehmen. Und womöglich muss der Benutzer zuerst die 10 Integer-Werte einfüllen. Er soll sie aber auch bearbeiten können. Alles funktioniert also über die gleiche Funktion, bearbeiten und erste Mal befüllen. Dabei wird zuerst das Array ausgegeben. Damit es halt ein wenig schön aussieht, wäre es nett, wenn es standard mässig mit 0s gefüllt ist.

    Grüssli



  • Hallo

    Dravere schrieb:

    Wenn die Grösse konstant ist, wirst du ja wohl nicht einen Vektor nehmen

    Warum? Ich nehme immer vector oder halt andere container, aber keine normalen arrays mehr.

    chrische



  • Dravere schrieb:

    @Simon2,
    Konstruktor schön und gut, aber dort musst du dann trotzdem die Nullen reinsetzen ^^

    Nö, das meinte Simon2 nicht. Sondern sowas (das ist jetzt echt nur zur Veranschaulichung und heißt nicht, das man solche Typen bauen muß!!! Aber wer will... kann das machen):

    class Integer
    {
        int value;
    
        public:
          Integer()
          { value  = 0; }
        // zusätzlich noch die Operatoren wie +, -, = usw. überladen!!!
    };
    
    Integer a[10]; // autom wird der Ctor aufgerufen und 0 initialisiert
    cout << a[0] ; // gibt 0 aus
    a[0] = 2;
    cout << a[0]; // gibt 2 aus
    

    Vorteil bei C++ ist halt, das alle Klassen als Build-in-Types designed werden können.

    Dravere schrieb:

    Wenn die Grösse konstant ist, wirst du ja wohl nicht einen Vektor nehmen. Und womöglich muss der Benutzer zuerst die 10 Integer-Werte einfüllen.

    Nein, bei Vector ebend nicht:

    vector<int> a(10,0); // 10 Elemenete mit 0 initialisieren
    

    Dravere schrieb:

    Damit es halt ein wenig schön aussieht, wäre es nett, wenn es standard mässig mit 0s gefüllt ist.

    Bei ISO-C++ lautet die Devise: bezahle nur für das, was du auch haben willst. Da das initialisere von solchen Arrays zur Laufzeit Rechenzeit kostet, wird das ebend nicht standardmäßig gemacht. Wenn du es haben willst, kannst du es aufrufen und bekommst es auch. Notfalls bauste dir einen eigenen Typ, der im Ctor alles macht, was du haben willst. Für dich, der es benutzt, ist es dann egal ob du int oder Integer benutzt. Oder du machst ein std::fill.



  • RHBaum schrieb:

    ...Den wiederum kannst ned vorschreiben, was fuern compiler sie zu verwenden haben. ...

    Nee, braucht man auch nicht. Sourcecode (inkl. Std-Makefile) geben und fertig. Sofern man sich an den Standard gehalten hat, dürften die auch keinen Probleme haben. 😃

    RHBaum schrieb:

    ...
    Will damit ja nur sagen, dass man leider noch auf das gute alte C angewiesen ist, ...

    Definitiv richtig !
    Ich glaube, selbst wenn die C++-Standardisierung da noch was nachbessert, wird C (zumindestens) für APIs noch sehr lange benötigt werden (allein schom weil sie etabliert ist).

    Ich sehe und teile Deinen Punkt - es ist für mich nur kein Argument, prinzipiell nach einem calloc-Pendant in C++ zu suchen.

    Gruß,

    Simon2.



  • Dravere schrieb:

    @Simon2,
    Konstruktor schön und gut, aber dort musst du dann trotzdem die Nullen reinsetzen ^^

    class ClassX
    {
    public:
        ClassX()
        { std::fill(m_IntegerArray, m_IntegerArray + 10, 0); }
    
    private:
        int m_IntegerArray[10];
        const static int m_nLength = 10;
    
    public:
        void display();
        void edit();
    }
    

    ...

    Was Du da ber tust, ist nicht "Speicherbereiche auf 0 setzen", sondern Objekte !
    hier sind's halt ints, aber der code würde exakt so funktionieren, wenn Du stattdessen irgendwelche selbstgebastelten Klassen (und leicht verallgemeinert sogar mit nahezu beliebigen Containern statt build-in-arrays) nähmst.
    Der Unterschied wird vielleicht noch deutlicher, wenn Du nicht auf 0, sondern z.B. auf 10 setzen wollen würdest: Mit memset() kämst Du da in Teufels Küche und müsstest Dich mit der interenen Repräsentation Deines Datentype auseinandersetzen.
    Mit std::fill wäre das lediglich das Hinzufügen einer '1'. 😃

    Dravere schrieb:

    ...Damit es halt ein wenig schön aussieht, wäre es nett, wenn es standard mässig mit 0s gefüllt ist.

    Grüssli

    Das mag Deinem persönlichen Standard und ästhetischem Empfinden "schön" sein, ich halte das für irgendwas zwischen "überflüssig", "verwirrend" und "gefährlich" (spätestens dann, wenn man beginnt sich darauf zu verlassen, dass ja "alles schon genullt ist") ....
    Der (C++-)Standard sieht für die Initialisierung von Objekten dn Konstruktor vor und geht davon aus, dass dort Daten auf einen fachlich sinnvollen Wert gesetzt werden ... ob das 0 ist, sollte man IMO von Fall zu Fall entscheiden.

    Gruß,

    Simon2.


Anmelden zum Antworten