2012-04-05 10 views
7

ich ein Problem mit auto_ptr in Ausnahmeklassen haben, dass ich schließlich reduziert:Warum kann ich nicht haben eine auto_ptr in einer Ausnahmeklasse

#include <memory> 

class MyException 
{ 
    std::auto_ptr<int> m_foo2; 
}; 

int main() 
{ 
    try 
    { 
     throw MyException(); 
    } 
    catch (const MyException&) 
    { 

    } 
    return 0; 
} 

Dies irgendwie kompilieren:

/perforce/unstable/test/Common/Exceptions/TestException4.cpp: In function 'int main()': /perforce/unstable/test/Common/Exceptions/TestException4.cpp:12: error: no matching function for call to 'MyException::MyException(MyException)' /perforce/unstable/test/Common/Exceptions/TestException4.cpp:4: note: candidates are: MyException::MyException() /perforce/unstable/test/Common/Exceptions/TestException4.cpp:4: note: MyException::MyException(MyException&) /perforce/unstable/test/Common/Exceptions/TestException4.cpp:12: error: in thrown expression

Und der Fehler verschwindet, wenn ich den auto_ptr entfernen.

Liegt das daran, dass die Ausnahme kopiert oder zugewiesen wird? Gibt es eine Möglichkeit, auto_ptr s in einer Ausnahme zu verwenden?

+0

Wow, qualitativ hochwertige Antworten hier. Muss eine gute Frage sein. :) – sje397

Antwort

9

Is this because the exception is being copied or assigned?

In der Tat ist es. Der Standard spezifiziert, wie eine Ausnahme geworfen wird in C++ 11 15.1/3:

A throw-expression initializes a temporary object, [...]. The temporary is an lvalue and is used to initialize the variable named in the matching handler.

Die Initialisierung wird mit dem impliziten Copykonstruktor getan. Dies wird als MyException(MyException&) deklariert, da es ein Member gibt, das ein nicht-const Referenzargument erfordert (wie in C++ 11 12.8/9 angegeben). Das temporäre Objekt kann nicht an eine nicht const Referenz gebunden werden, und so schlägt die Konstruktion fehl.

Is there a way of using auto_ptrs in an Exception?

Wenn Sie in der Lage sind C 11 ++ verwenden, dann könnten Sie unique_ptr verwenden stattdessen und consign auto_ptr zu den Eingeweiden der Geschichte. Ihre Klasse würde einen impliziten Move-Konstruktor haben, der als MyException(MyException&&) deklariert ist, der dazu verwendet werden könnte, ihn von einem temporären zu initialisieren.

Andernfalls könnten Sie einen nicht nur vorübergehenden Wert werfen:

MyException ex; 
throw ex; 

oder Sie können Ihre Klasse hacken Initialisierung von einem const Bezug zu ermöglichen, indem eine explizite Copykonstruktor Hinzufügen und const_cast oder mutable verwenden, das zu ermöglichen, Kopieren Sie die auto_ptr - aber das ist möglicherweise gefährlich, und ich würde es nicht empfehlen.

Verwandte Themen