Effective C + + clause 08: Don't let exceptions escape from destructors __jquery

Source: Internet
Author: User
1. Don't let the exception escape the reason for the destructor

Article 08 of the third edition of effective C + + recommends that you do not throw an exception in a destructor because the C + + exception mechanism cannot handle two or more than two exceptions at the same time. Where multiple exceptions exist at the same time, if the program does not end, it can cause ambiguous behavior. the following code:

Class widget{public
:
    ~widget () {...}    Suppose this may spit out an exception
};
void DoSomething () {
    vector<widget> v;
}                    The V is automatically destroyed here.

After the function dosomething run, the vector V of the most stack object will be destroyed, and it also has the responsibility to destroy all the widgets contained therein. Suppose V contains 10 widgets, and an exception is thrown during the first element of the destructor. The other nine widgets should still be destroyed (otherwise any resources they save will leak), so v should call their various destructors. But suppose that during those calls, the second widget destructor throws an exception, which appears as described above, where multiple exceptions exist at the same time, and if the program does not end, it can cause ambiguous behavior. 2. Solutions

What to do if the destructor must perform an action, and the action might throw an exception on failure. For example, suppose you use one class for the database connection:

Class DbConnection {public 
:
...
Static dbconnection Create (); Returns the DbConnection object, simplifies the temporary parameter
void close (),//closes online, and throws an exception if it fails.
};

To ensure that the customer does not forget to call Close () on the DbConnection object, a reasonable idea is to create a class that manages the dbconection resource and call close in its destructor. This is famous for managing resources with objects .

Class Dbconn {//This class is used to manage DbConnection objects public 
:
...
Dbconn (const dbconnection& db) {
       this->db=db;
   }
~dbconn ()//Ensure that the database connection will always be closed
{    db.close ();
Private:
dbconnection db;
  

Call Close success, everything is fine. But if the call causes an exception, the Dbconn destructor propagates the exception, which means it is allowed to leave the destructor. That can cause problems, and the solution is as follows:
(1) method One: Closing the procedure
If close throws an exception to end the program, it is usually done by calling Abort:

Dbconn::~dbconn () {
    try {
        db.close ();}
    catch (...) {
        abort ();
    }
}

If a program encounters an "error in the destructor" that cannot continue after execution, the "Force End Program" is a reasonable option, after all, it can prevent the exception from being propagated from the destructor (which can result in ambiguous behavior). That is to say, call abort can preempt "ambiguous behavior" to death.

(2) method two: Swallow the exception that occurred because of calling close

dbconn::~dbconn{
    try{db.close ();}
    catch (...) {
        //make a running record, note that the call to close failed.
    }
}

In general, it is a bad idea to swallow an exception because it suppresses important information about "some action failure". However, sometimes it is better to swallow an exception than to bear the risk of "hasty termination" or "ambiguous conduct". In order for this to be a viable option, the process must be able to continue to perform reliably.

(3) method Three: redesign the Dbconn interface so that its customers have the opportunity to respond to possible anomalies
We can add a close function to Dbconn, giving the customer an opportunity to handle "exceptions due to this operation." By moving the responsibility to call close from the Dbconn destructor to the Dbconn client, you might think it violates the "let the interface be used correctly" advice. In fact, this stigma is not tenable. If an operation might throw an exception when it fails, and there is a need to handle the exception, the exception must come from a function other than the destructor. Because destructors spit out exceptions are dangerous, there is always the risk of "prematurely ending the program" or "ambiguous behavior".

Class Dbconn {public
:
    ...
    void Close ()//new function for customer use
    {
        db.close ();
        closed = true;
    }
    ~dbconn () {if
        (!closed) {
            try {       //close connection if client does not invoke Dbconn::close)
                  db.close ();
            }
            catch (...) {///If the shutdown action fails, record and end the program or swallow the exception.
                make a running record, note that the call to close failed;
Private:
    dbconnection db;
    bool closed;
};

In this case, the call to close by the customer does not burden them, but gives them an opportunity to handle the error. If they do not consider this opportunity useful (perhaps they believe there will be no error), they may ignore it and rely on the Dbconn destructor to invoke close.

Please remember:
(1) Destructors should never spit out exceptions, and if a function called by a destructor might throw an exception, the destructor should catch any exceptions and swallow them (not propagate) or end the program.
(2) If the customer needs to react to an exception thrown during the operation of an action function, class should provide a normal function (rather than in the destructor) to perform the operation. Reference Documents

[1] Effective C + + Learning notes-clause 08: Don't let exceptions escape from destructors

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.