Laut einem sachkundigen Autor innerhalb der C ++ - Community sollte der nachstehende Code nicht kompiliert werden. Ist er falsch?

StackOverflow https://stackoverflow.com/questions/8367459

Frage

Laut Herb Sutter würde der folgende Code nicht kompilieren. Siehe diese Seite http://www.gotw.ca/gotw/066.htm Von wo aus ich den folgenden Text extrahiert habe, bezüglich function-try-blocks :

Auf einige Moral

Dies bedeutet übrigens auch, dass die einzige (nur Wiederholung) für einen Konstruktorfunktionsblock möglichen Gebrauch darin besteht, eine Ausnahme von einem Basis- oder Element-Unterobjekt zu übersetzen. Das ist moralisch #1. Als nächstes besagt Moral #2, dass Destructor-Funktionsblocks völlig wir uns sind-

"--Aber warte!" Ich höre jemanden, der sich von der Mitte des Raums unterbricht. "Ich stimme Moral Nr. 1. nicht zu. Ich kann mir eine andere mögliche Verwendung für Konstruktor-Funktionsblocks vorstellen, nämlich kostenlose Ressourcen, die in der Initialisiererliste oder in der Konstruktorität zugewiesen wurden!"

Entschuldigung, nein. Denken Sie schließlich daran, dass, sobald Sie in Ihren Konstruktor-Try-Block-Handler einsteigen, alle lokalen Variablen in der Konstruktor-Körperschaft ebenfalls aus dem Zielfernrohr sind, und es wird Ihnen garantiert, dass keine Basis-Unterobjekte oder Mitgliedsobjekte mehr vorhanden sind. Sie können sich nicht einmal auf ihre Namen beziehen. Entweder wurden die Teile Ihres Objekts nie konstruiert, oder die konstruierten, die konstruiert wurden, wurden bereits zerstört. Sie können also nichts aufräumen, das sich auf eine Basis oder ein Mitglied der Klasse bezieht (und darauf, wofür die Basis- und Mitgliedszerstörer sind, oder?).

Unter der Annahme dieses Zitats sollte der folgende Code nicht als Objekt kompilieren cat wurde bereits zerstört, wenn der Prozess in die läuft catch Klausel. Aber zumindest mit VSC2008.

class Cat
{
    public:
    Cat() { cout << "Cat()" << endl; }
    ~Cat() { cout << "~Cat()" << endl; }
};

class Dog
{
    public:
    Dog() { cout << "Dog()" << endl; throw 1; }
    ~Dog() { cout << "~Dog()" << endl; }
};


class UseResources
{
    class Cat *cat;
    class Dog dog;

    public:
    UseResources();
    ~UseResources() { delete cat; cat = NULL; cout << "~UseResources()" << endl; }
};

UseResources::UseResources() try : cat(new Cat), dog() { cout << "UseResources()" << endl; } catch(...)
{
    delete cat;
    throw;
}
War es hilfreich?

Lösung

Ich glaube nicht, dass Herb Sutter tatsächlich sagt, dass es nicht kompiliert wird. Er erklärt nur die Konsequenzen dessen, was der Standard über die Situation zu sagen hat (15.3.10):

Bezieht sich auf ein nicht statisches Mitglied oder eine Basisklasse eines Objekts im Handler für einen Funktionsblock eines Konstruktors oder Destruktors für dieses Objekt führt dazu undefiniertes Verhalten.

Andere Tipps

Unter der Annahme dieses Zitats sollte der folgende Code nicht kompilieren ...

Nun, er sagte nicht, dass sie niemals zusammenstellen würden. Wenn überhaupt, habe ich das Zitat so interpretiert, dass "dies undefiniert ist". Und definiertes Verhalten darf ein Ergebnis erzielen - bis hin zu erfolgreichem Zusammenstellen und später überraschende Dinge.

Compiler sind unterschiedlich, und es gibt auch Switches, die bestimmen, wie viel der Compiler mit dem Code, den er kompiliert, streng sein wird. Dieser Code wird sicherlich Fehler verursachen (SEG -Fehler usw.). Versuchen Sie, alle Schalter des Compilers zu ermöglichen, dies zu zwingen, dies zu finden.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top