unique_ptr und vector resize



  • Hallo zusammen,

    ich habe den unique_ptr von c++0x ausprobiert und einen std::vector<std::unique_ptr<MyObject>> angelegt mit dem ich bis jetzt gut klar gekommen bin. Nun möchte ich die resize Methode darauf aufrufen und bekomme folgenden Fehler:

    ...
    /usr/include/c++/4.4/bits/unique_ptr.h:214: error: deleted function ‘std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = MyObject, _Tp_Deleter = std::default_delete<MyObject>]’
    /usr/include/c++/4.4/bits/stl_construct.h:74: error: used here
    

    Weiß jemand Rat?

    Lg, Jaz



  • ein google nach "C++0x deleted function" liefert http://www2.research.att.com/~bs/C++0xFAQ.html#default
    Schlussfolgerung: unique_ptr ist noncopyable. vector verlangt aber kopierbare elemente. => vector<unique_ptr<>> läuft nicht.



  • Die Fehlermeldung hört sich tatsächlich so an, aber wieso gibt es dann zig Tutorials (z.B. http://www.devx.com/cplus/10MinuteSolution/39071/1954), wo das Zusammenspiel von unique_ptr und vector erklärt wird? Außerdem muss der vector ja auch seine Daten auch intern umkopieren, wenn er wächst, d.h. es dürfte auch nicht kompilieren wenn ich nicht explizit resize verwenden würde. Dann funktioniert es aber.



  • Jazq schrieb:

    Die Fehlermeldung hört sich tatsächlich so an, aber wieso gibt es dann zig Tutorials (z.B. http://www.devx.com/cplus/10MinuteSolution/39071/1954), wo das Zusammenspiel von unique_ptr und vector erklärt wird? Außerdem muss der vector ja auch seine Daten auch intern umkopieren, wenn er wächst, d.h. es dürfte auch nicht kompilieren wenn ich nicht explizit resize verwenden würde. Dann funktioniert es aber.

    Vielleicht musst du eine neuere Compilerversion benutzen? Du scheinst einen gcc 4.4 zu benutzen, aktuell ist aber 4.5. Die c++-0x Implementierung ist bestimmt noch nicht fehlerfrei.

    Lars



  • Jazq schrieb:

    Die Fehlermeldung hört sich tatsächlich so an, aber wieso gibt es dann zig Tutorials (z.B. http://www.devx.com/cplus/10MinuteSolution/39071/1954), wo das Zusammenspiel von unique_ptr und vector erklärt wird?

    Das erste was ich unter deinem Link zum vector + unique_ptr gefunden habe ist folgender Satz:

    If a container of unique_ptr objects moves elements internally instead of copying them, your code will work without problems. If, however, a container or an algorithm uses copy semantics for its value_type you will get a compilation error.

    Ich bin kein C++0x Fachmann, aber ich vermute mal dass die neuen std::vector'en für "normale" Vergrößerungen (z.B. bei push_back) die move-semantik benutzen, die unique_ptr wohl unterstützen wird, während resize() offenbar was anderes macht - evtl. werden die neuen Elemente mit dem optionalen Werte-Parameter von resize() copy-konstruiert? Wo genau der Copy-Ctor aufgerufen wird siehst du vermutlich an der bezeichneten Stelle - stl_construct.h, Zeile 74



  • Jazq schrieb:

    aber wieso gibt es dann zig Tutorials (z.B. http://www.devx.com/cplus/10MinuteSolution/39071/1954), wo das Zusammenspiel von unique_ptr und vector erklärt wird?

    In C++0x (noch nicht fertige kommende Revision des C++ Standards) wird std::vector auch Typen wie unique_ptr verarbeiten können. Das heißt aber nicht, dass jede Operation auch unterstützt wird. Da unique_ptr nicht kopierbar ist, kannst Du resize auch nicht benutzen; denn resize will ggf einen default-konstruierten oder übergebenen unique_ptr mehrfach in den Vektor kopieren.

    Füllen kannst Du diesen Vektor beispielsweise mit reserve und push_back oder emplace_back:

    vector<unique_ptr<int> > vec;
    vec.reserve(100);
    for (int i=0; i<100; ++i) {
      vec.push_back( unique_ptr<int>(0) );
    }
    

    (ungetestet).

    Jazq schrieb:

    Außerdem muss der vector ja auch seine Daten auch intern umkopieren, wenn er wächst, d.h. es dürfte auch nicht kompilieren wenn ich nicht explizit resize verwenden würde. Dann funktioniert es aber.

    In C++0x wird der Vektor nicht alles kopieren müssen. Ein unique_ptr-Objekt kann von einem Ort zu einem anderen "umziehen". Und das wird im Vektor auch so gemacht. Manuell geht das so:

    unique_ptr<int> p (new int);
    *p = 23;
    unique_ptr<int> q = std::move(p);
    cout << *q << endl;
    if (!p) {
      cout << "p ist jetzt ein Nullzeiger" << endl;
    }
    

    kk


Anmelden zum Antworten