3 Stimmen

Warum setzt std::auto_ptr Operator = Objekte auf den Müll?

Scheint ein Problem mit std::auto_ptr und Zuweisung zu haben, sodass das referenzierte Objekt aus irgendeinem Grund beschädigt zu werden scheint.

std::auto_ptr someVar = new AClass();  // sollte funktionieren, aber verändert den Inhalt
std::auto_ptr someVar( new AClass() ); // funktioniert einwandfrei.
std::auto_ptr someVar = std::auto_ptr(new AClass()); // funktioniert einwandfrei.

std::auto_ptr someVar;
someVar.reset( new AClass() ); // funktioniert einwandfrei.

Ich habe es verfolgt und es scheint (durch Beobachten der Werte im Debugger), dass das Problem beim Transfer des Zeigers von der temporären std::auto_ptr_byref() auftritt, die erstellt wird, um den rhs-Zeiger zu umschließen. Der Wert von _Right beim Betreten der Funktion auto_ptr(auto_ptr_ref<_Ty> _Right) ist korrekt, aber der Wert von _Myptr beim Verlassen ist Müll.

template
    struct auto_ptr_ref
        {   // Proxy-Referenz für auto_ptr-Kopieren
    auto_ptr_ref(void *_Right)
        : _Ref(_Right)
        {   // Konstruktor aus generischem Zeiger auf auto_ptr-Zeiger
        }

    void *_Ref; // Generischer Zeiger auf auto_ptr-Zeiger
    };

template
class auto_ptr
    {   // Ein Objektzeiger einhüllen, um die Zerstörung sicherzustellen
public:
typedef _Ty element_type;

explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
    : _Myptr(_Ptr)
    {   // Konstruktor aus Objektzeiger
    }

auto_ptr(auto_ptr<_Ty>& _Right) _THROW0()
    : _Myptr(_Right.release())
    {   // Konstruktor, indem der Zeiger von _Right auto_ptr angenommen wird
    }

auto_ptr(auto_ptr_ref<_Ty> _Right) _THROW0()
    {   // Konstruktor, indem der Zeiger von _Right auto_ptr_ref angenommen wird
    _Ty **_Pptr = (_Ty **)_Right._Ref;
    _Ty *_Ptr = *_Pptr;
    *_Pptr = 0; // Alten freigeben
    _Myptr = _Ptr;  // Diesen zurücksetzen
    }
auto_ptr<_Ty>& operator=(auto_ptr_ref<_Ty> _Right) _THROW0()
{   // Kompatibles _Right._Ref zuweisen (Zeiger annehmen)
_Ty **_Pptr = (_Ty **)_Right._Ref;
_Ty *_Ptr = *_Pptr;
*_Pptr = 0; // Alten freigeben
reset(_Ptr);    // neues setzen
return (*this);
}

Zu Beginn dachte ich, es würde das Vererben durcheinanderbringen und Schnittstellen abschneiden, jedoch geschieht dies selbst, wenn die Klasse nur eine Elternklasse hat.

Wir können vermeiden, = new zu verwenden, wenn wir uns entweder an Klammern erinnern oder zu einem expliziten std::auto_ptr temp auf dem rhs wechseln, das ist natürlich fehleranfällig.

Handelt es sich nur um diese Version der Bibliothek, die defekt ist, oder um etwas grundlegendes, was ich nicht verstehe?

Wir haben auch ein ähnliches Problem mit der Zuweisung eines std::auto_ptr an ein boost::shared_ptr bemerkt, obwohl wir das jetzt komplett entfernt haben und ich mich nicht mehr daran erinnere, welche Syntax das Problem verursacht hat.

10voto

Michael Burr Punkte 320591

Die erste Zeile:

std::auto_ptr someVar = new AClass();  // sollte funktionieren, aber verfälscht den Inhalt

sollte zu einem Compilerfehler führen. Da es keine implizite Konvertierung vom reinen AClass Zeiger zu einem auto_ptr gibt (der Konstruktor für ein auto_ptr, der einen reinen Zeiger akzeptiert, ist als explicit markiert), ist eine Initialisierung mit der 'Kopierinitialisierer'-Form nicht erlaubt.

VC9 gibt den folgenden Fehler aus:

C:\temp\test.cpp(23) : error C2440: 'initializing' : kann nicht konvertieren von 'AClass *' zu 'std::auto_ptr<_Ty>'

Andere Compiler, die ich ausprobiert habe (GCC 3.4.5, Comeau C/C++ 4.3.10.1, Digital Mars), geben einen ähnlichen Fehler aus.

EDIT:

Es scheint, dass dies tatsächlich ein Bug in der Implementierung von auto_ptr<> in VS2005 ist (nicht sicher, ob er in SP1 eingeführt wurde oder von Anfang an in VS2005 war) und in VS2008 behoben wurde. Hier ist der MS Connect Bug-Eintrag zu dem Problem:

https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=101842&wa=wsignin1.0

4voto

MSalters Punkte 166675

0voto

Jesse Pepper Punkte 3225

Bearbeitet: Michael hat völlig recht, es handelt sich um einen Kompilierungsfehler. Welchen Compiler benutzen Sie? Sie müssen reset aufrufen, um einen neuen Wert dem auto_ptr zuzuweisen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X