std::vector Frage



  • Arcoth schrieb:

    DocShoe schrieb:

    Mit std::iota .

    Edit:
    Sehe grad, dass deine Klasse dann den ++operator implementieren muss.

    Du hast eher versäumt zu sehen, dass der TE den Konstruktor (aus Unwissenheit?) nicht als explicit deklariert hat:

    #include <iterator>
    #include <numeric>
    int main() {
        Example e[10];
        std::iota(std::begin(e), std::end(e), 0);
    }
    

    kompiliert nicht.
    https://ideone.com/AFdvzG
    zu mindestens nicht mit C++14


  • Mod

    Hast Du die Fehlermeldung gelesen?


  • Mod

    Arcoth schrieb:

    Hast Du die Fehlermeldung gelesen?

    Kommt dir die Frage nicht berechtigt vor? Das Problem ist schließlich nicht zu beheben, ohne entweder die Eigenschaften der Klasse erheblich zu ändern, oder dein Beispiel erheblich abzuändern.


  • Mod

    SeppJ schrieb:

    Arcoth schrieb:

    Hast Du die Fehlermeldung gelesen?

    Kommt dir die Frage nicht berechtigt vor? Das Problem ist schließlich nicht zu beheben, ohne entweder die Eigenschaften der Klasse erheblich zu ändern

    Wirklich? Ein Default Argument für den Konstruktor hältst du für eine erhebliche Änderung?

    class Example
    {
    private:
      int id;
    public:
      Example(int i = 0): id(i);
    };
    

    Ich bin überzeugt, dass firefly sich nicht einmal die Mühe gemacht hat, die 10 Sekunden zu investieren, die es braucht, um diese Fehlermeldung zu beheben.

    Es gibt Grenzen, Seppl. Grenzen.


  • Mod

    Arcoth schrieb:

    SeppJ schrieb:

    Arcoth schrieb:

    Hast Du die Fehlermeldung gelesen?

    Kommt dir die Frage nicht berechtigt vor? Das Problem ist schließlich nicht zu beheben, ohne entweder die Eigenschaften der Klasse erheblich zu ändern

    Wirklich? Ein Default Argument für den Konstruktor hältst du für eine erhebliche Änderung?

    Ja? Dir nicht? Du weißt überhaupt nichts über die Bedeutung des Arguments. Was ist, wenn das etwas essentielles für die Identität der Klasse ist? Besonders, da schon gesagt wurde, dass temporäre Objekte vermieden werden sollen, da der Konstruktor Nebeneffekte hat.

    Könnten zum Beispiel TCP-Verbindungen über Ports 8001-8100 sein, da wäre es fatel, einfach ein Default 0 einzuführen und das als kleine Änderung abzutun.

    Es gibt Grenzen, Seppl. Grenzen.

    Das ist nicht mein Name.



  • Arcoth schrieb:

    Wirklich? Ein Default Argument für den Konstruktor hältst du für eine erhebliche Änderung?

    heartless schrieb:

    da der Destruktor der Klasse Seiteneffekte enthält.

    Hört sich so an.


  • Mod

    Ihr habt wohl nicht erfasst, dass es sich hier um ein Pseudo- Example innerhalb von Pseudocode handelt, dass lediglich meiner Demonstration von iota dient. Es ist doch ersichtlich, dass die nötige Änderung meinem Einsatz eines Arrays statt des vector s geschuldet ist, und nicht dem Einsatz von iota selbst. Ich habe doch nie behauptet, dass mein Code mehr als Pseudo-Code ist, dessen einzige bedeutungsvolle Zeile der iota -Aufruf ist. Und genauso fordere ich firefly auf, das Beispiel selbst auf die im Eingangspost gegebene Definition von Example zu übertragen. Soll ich hier jeden trivialen Quatsch vorkauen, damit copy&paste ausreicht?

    SeppJ schrieb:

    Es gibt Grenzen, Seppl. Grenzen.

    Das ist nicht mein Name.

    Soll ich Dich beim Klarnamen nennen, oder fändest Du das schon dreist? Was für eine Sorte von Forenmitglied nimmt einem ein harmloses Wortspiel mit deren moniker übel?



  • @Arcoth
    Sei mal nicht so eingeschnappt. Wortspiele mit dem Namen nimmt man schnell mal übel, speziell wenn man in einer Diskussion diametrale Positionen hat.


  • Mod

    hustbaer schrieb:

    @Arcoth
    Sei mal nicht so eingeschnappt. Wortspiele mit dem Namen nimmt man schnell mal übel, speziell wenn man in einer Diskussion diametrale Positionen hat.

    Man sollte aber sein Unbehagen auf eine Weise ausdrücken, die mich nicht entfremdet. Hab's doch nicht so gemeint. 😞



  • @ heartless
    Die einfachste Lösung wäre wohl einen std::vector<std::unique_ptr<Foo>> statt eines std::vector<Foo> zu verwenden. Damit kontrollierst du explizit wann ein Objekt erzeugt bzw. zerstört wird, der std::vector funkt dir in keiner Weise dazwischen.



  • Arcoth schrieb:

    Ihr habt wohl nicht erfasst, dass es sich hier um ein Pseudo- Example innerhalb von Pseudocode handelt, dass lediglich meiner Demonstration von iota dient. Es ist doch ersichtlich, dass die nötige Änderung meinem Einsatz eines Arrays statt des vector s geschuldet ist, und nicht dem Einsatz von iota selbst. Ich habe doch nie behauptet, dass mein Code mehr als Pseudo-Code ist, dessen einzige bedeutungsvolle Zeile der iota -Aufruf ist. Und genauso fordere ich firefly auf, das Beispiel selbst auf die im Eingangspost gegebene Definition von Example zu übertragen. Soll ich hier jeden trivialen Quatsch vorkauen, damit copy&paste ausreicht?

    Ich habe die Example class definiton aus dem eigangspost genommen und da ist keinerlei default argument gegeben für den parameter im konstruktor.
    Oder was meinst du sonst?


  • Mod

    firefly schrieb:

    Arcoth schrieb:

    Ihr habt wohl nicht erfasst, dass es sich hier um ein Pseudo- Example innerhalb von Pseudocode handelt, dass lediglich meiner Demonstration von iota dient. Es ist doch ersichtlich, dass die nötige Änderung meinem Einsatz eines Arrays statt des vector s geschuldet ist, und nicht dem Einsatz von iota selbst. Ich habe doch nie behauptet, dass mein Code mehr als Pseudo-Code ist, dessen einzige bedeutungsvolle Zeile der iota -Aufruf ist. Und genauso fordere ich firefly auf, das Beispiel selbst auf die im Eingangspost gegebene Definition von Example zu übertragen. Soll ich hier jeden trivialen Quatsch vorkauen, damit copy&paste ausreicht?

    Ich habe die Example class definiton aus dem eigangspost genommen und da ist keinerlei default argument gegeben für den parameter im konstruktor.
    Oder was meinst du sonst?

    Natürlich ist da keiner. Das soll auch so bleiben. In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötigt. Das ändert aber nichts an der Anwendbarkeit von iota . Und Du hättest das Problem auch sofort erkannt, wenn Du die Fehlermeldung gelesen hättest, womit sich deine Frage erübrigt hätte. Nichts für Ungut, aber ich hab einfach nichts für solche unüberlegten Kommentare übrig.



  • Arcoth schrieb:

    In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötig.

    Und mit einem vector würde es ohne Defaultkonstruktor funktionieren?


  • Mod

    manni66 schrieb:

    Arcoth schrieb:

    In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötig.

    Und mit einem vector würde es ohne Defaultkonstruktor funktionieren?

    😕

    std::vector<Example> vec(0, 10);
    std::iota(std::begin(e), std::end(e), 0);
    

  • Mod

    Arcoth schrieb:

    manni66 schrieb:

    Arcoth schrieb:

    In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötig.

    Und mit einem vector würde es ohne Defaultkonstruktor funktionieren?

    😕

    std::vector<Example> vec(0, 10);
    std::iota(std::begin(e), std::end(e), 0);
    

    😕
    Sprich: Nein, es würde nicht funktionieren? Ob du nun implizit ein Array mit 0 initialisierst oder einen Vector explizit mit 0, macht doch dein Beispiel nicht besser. In jedem Fall legst du unnötige, und ausdrücklich nicht gewünschte Defaultobjekte an, bevor du die korrekten Objekte erzeugst.

    Ich bin sehr verwirrt: Wer bist du und was hast du mit dem echten Arcoth gemacht?



  • SeppJ schrieb:

    Arcoth schrieb:

    manni66 schrieb:

    Arcoth schrieb:

    In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötig.

    Und mit einem vector würde es ohne Defaultkonstruktor funktionieren?

    😕

    std::vector<Example> vec(0, 10);
    std::iota(std::begin(e), std::end(e), 0);
    

    😕
    Sprich: Nein, es würde nicht funktionieren? Ob du nun implizit ein Array mit 0 initialisierst oder einen Vector explizit mit 0, macht doch dein Beispiel nicht besser. In jedem Fall legst du unnötige, und ausdrücklich nicht gewünschte Defaultobjekte an, bevor du die korrekten Objekte erzeugst.

    Ich stimme prinzipiell zu, allerdings hat der OP klargemacht, dass er solche Objekte wegen ihres Destruktors vermeiden möchte - ein Destruktor wird hier aber so wie ich das sehe nirgends aufgerufen, wodurch Arcoth's Lösung technisch gesehen schon den Anforderungen genügen würde.

    SeppJ schrieb:

    Ich bin sehr verwirrt: Wer bist du und was hast du mit dem echten Arcoth gemacht?

    Was die Pubertät so mit den Menschen macht... *duckundweg*


  • Mod

    Jodocus schrieb:

    SeppJ schrieb:

    Arcoth schrieb:

    manni66 schrieb:

    Arcoth schrieb:

    In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötig.

    Und mit einem vector würde es ohne Defaultkonstruktor funktionieren?

    😕

    std::vector<Example> vec(0, 10);
    std::iota(std::begin(e), std::end(e), 0);
    

    😕
    Sprich: Nein, es würde nicht funktionieren? Ob du nun implizit ein Array mit 0 initialisierst oder einen Vector explizit mit 0, macht doch dein Beispiel nicht besser. In jedem Fall legst du unnötige, und ausdrücklich nicht gewünschte Defaultobjekte an, bevor du die korrekten Objekte erzeugst.

    Ich stimme prinzipiell zu, allerdings hat der OP klargemacht, dass er solche Objekte wegen ihres Destruktors vermeiden möchte - ein Destruktor wird hier aber so wie ich das sehe nirgends aufgerufen, wodurch Arcoth's Lösung technisch gesehen schon den Anforderungen genügen würde.

    Wenn der Konstruktor tatsächlich Ressourcen belegt, was der Beschreibung zufolge anzunehmen ist, dann muss eine Zuweisung die überschriebene Ressource auch wieder freigeben (weshalb man in diesem Fall die Zuweisung normalerweise mit Copy&Swap implementiert). Dies ist fast mit Sicherheit der Fall, denn sonst wäre nicht betont worden, dass unnötige Konstruktor und Destruktoraufrufe vermieden werden sollten. Was einen nicht-trivialen Destruktor und damit auch eine nicht-triviale Zuweisung impliziert.

    Jodocus schrieb:

    SeppJ schrieb:

    Ich bin sehr verwirrt: Wer bist du und was hast du mit dem echten Arcoth gemacht?

    Was die Pubertät so mit den Menschen macht... *duckundweg*

    Ich bin ziemlich sicher, dass Arcoth Anfang bis Mitte 20 ist.



  • SeppJ schrieb:

    Jodocus schrieb:

    SeppJ schrieb:

    Arcoth schrieb:

    manni66 schrieb:

    Arcoth schrieb:

    In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötig.

    Und mit einem vector würde es ohne Defaultkonstruktor funktionieren?

    😕

    std::vector<Example> vec(0, 10);
    std::iota(std::begin(e), std::end(e), 0);
    

    😕
    Sprich: Nein, es würde nicht funktionieren? Ob du nun implizit ein Array mit 0 initialisierst oder einen Vector explizit mit 0, macht doch dein Beispiel nicht besser. In jedem Fall legst du unnötige, und ausdrücklich nicht gewünschte Defaultobjekte an, bevor du die korrekten Objekte erzeugst.

    Ich stimme prinzipiell zu, allerdings hat der OP klargemacht, dass er solche Objekte wegen ihres Destruktors vermeiden möchte - ein Destruktor wird hier aber so wie ich das sehe nirgends aufgerufen, wodurch Arcoth's Lösung technisch gesehen schon den Anforderungen genügen würde.

    Wenn der Konstruktor tatsächlich Ressourcen belegt, was der Beschreibung zufolge anzunehmen ist, dann muss eine Zuweisung die überschriebene Ressource auch wieder freigeben (weshalb man in diesem Fall die Zuweisung normalerweise mit Copy&Swap implementiert). Dies ist fast mit Sicherheit der Fall, denn sonst wäre nicht betont worden, dass unnötige Konstruktor und Destruktoraufrufe vermieden werden sollten. Was einen nicht-trivialen Destruktor und damit auch eine nicht-triviale Zuweisung impliziert.

    Klar, so wird es wahrscheinlich auch sein. Aber es ist trotzdem erst mal nur Spekulation, bis der Threaderöffner Klarheit schafft.

    SeppJ schrieb:

    Jodocus schrieb:

    SeppJ schrieb:

    Ich bin sehr verwirrt: Wer bist du und was hast du mit dem echten Arcoth gemacht?

    Was die Pubertät so mit den Menschen macht... *duckundweg*

    Ich bin ziemlich sicher, dass Arcoth Anfang bis Mitte 20 ist.

    Okay, das war etwas fies. Ich denke, das ist einfach nur ein Fall von "wenn man einen Hammer hat, sieht die Welt aus wie ein Nagel". std::iota sah zu verlockend nach dem aus, was der TE vermutlich gebrauchen könnte.



  • SeppJ schrieb:

    Arcoth schrieb:

    manni66 schrieb:

    Arcoth schrieb:

    In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötig.

    Und mit einem vector würde es ohne Defaultkonstruktor funktionieren?

    😕

    std::vector<Example> vec(0, 10);
    std::iota(std::begin(e), std::end(e), 0);
    

    😕
    Sprich: Nein, es würde nicht funktionieren? Ob du nun implizit ein Array mit 0 initialisierst oder einen Vector explizit mit 0, macht doch dein Beispiel nicht besser. In jedem Fall legst du unnötige, und ausdrücklich nicht gewünschte Defaultobjekte an, bevor du die korrekten Objekte erzeugst.

    Zusätzlich zu den default objekten werden in jedem iota call ein temporary object erstellt:
    https://ideone.com/W7lAzJ
    Was noch weniger gewünscht ist vom OP


  • Mod

    Seppl schrieb:

    Arcoth schrieb:

    manni66 schrieb:

    Arcoth schrieb:

    In meiner Demonstration habe ich einfach flüchtig ein Array statt einem vector genommen, was einen Default-Konstruktor benötig.

    Und mit einem vector würde es ohne Defaultkonstruktor funktionieren?

    😕

    std::vector<Example> vec(0, 10);
    std::iota(std::begin(e), std::end(e), 0);
    

    😕
    Sprich: Nein, es würde nicht funktionieren? Ob du nun implizit ein Array mit 0 initialisierst oder einen Vector explizit mit 0, macht doch dein Beispiel nicht besser. In jedem Fall legst du unnötige, und ausdrücklich nicht gewünschte Defaultobjekte an, bevor du die korrekten Objekte erzeugst.

    Natürlich ist der Code furchtbar suboptimal. Was sowohl daran liegt, dass die Klasse ein RAII-konformes Interface hat, als auch dass iota_n in der STL fehlt. Dann machen wir es eben richtig:

    std::vector<Example> e;
    boost::algorithm::iota_n(back_inserter(e), 10, 0);
    
    // Oder (nicht ganz ernst gemeint)
    std::vector<Example> e;
    std::generate_n(back_inserter(e), 10,  [i = 0] () mutable {return Example(i++);});
    
    // Oder
    auto r = boost::irange(0, 9);
    std::vector<Example> e(r.begin(), r.end());
    

    Und in Bezug auf

    hustbaer schrieb:

    Die einfachste Lösung wäre wohl einen std::vector<std::unique_ptr<Foo>> statt eines std::vector<Foo> zu verwenden. Damit kontrollierst du explizit wann ein Objekt erzeugt bzw. zerstört wird, der std::vector funkt dir in keiner Weise dazwischen.

    // Oder
    std::vector<std::optional<Example>> e(10);
    std::iota(begin(e), end(e), 0);
    

    Der Punkt ist: man kann hier definitiv einen Nagel reinhauen, man muss nur hart genug schlagen! Auch wenn ich konzediere, dass mein ursprüngliches Beispiel nicht-trivial verändert werden muss, um es Sinn ergeben zu lassen. Dafür muss ich mich entschuldigen, ich habe das nicht mal ansatzweise durchdacht.

    @firefly: Diese Temporaries werden alle gemoved, vorausgesetzt der TE hat die Move-Semantik seiner Klasse richtig implementiert. Somit dürfte jeder entsprechende Destruktoraufruf ein no-op sein, da die Temporary keine Ressource mehr besitzt. Aber wie bereits erwähnt, das ist nur Spekulation.


Anmelden zum Antworten