Effective C + + 2nd structure/destructor/assignment operation (1)-Reading notes

Source: Internet
Author: User

Chapter Review:

The 1th chapter of effective C + + makes himself accustomed to c++-reading notes

Effective C + + 2nd structure/destructor/assignment operation (1)-Reading notes

"Effective C + +" 8th custom new and delete-reading notes

Article 05: Understand what functions C + + silently writes and calls

When C + + processes an empty class, the compiler declares it (the compiler Version): A copy constructor, a copy assignment operator, and a destructor. If you do not declare any constructors, the compiler also declares a default constructor. All of these functions are declared public and inline.

For example: Class empty{}; essentially:

class Empty {public:    empty () {...}                     // default constructor    Empty (const//  copy constructor    ~empty () {...}                //     operator= (const//  copy assignment operator};

Description

(1) only when these functions are called will they be created by the compiler.

(2) default constructors and destructors for example, constructors and destructors that call base classes and non-static member variables.

(3) the destructor generated by the compiler is non-virtual, unless the class's base class itself declares a virtual destructor.

Here's an example of how the compiler refuses to produce operator= for class.

template<classT>classNamedobject { Public: Namedobject (std::string& Name,Constt&value);Private: std::string& Namevalue;//This was now a reference    ConstT ObjectValue;//This was now const}STD::stringNewdog ("Persephone"); std::stringOlddog ("Satch"); Namedobject<int> P (Newdog,2); Namedobject<int> S (olddog, $);p= S;

C + + does not allow "let reference to point to different objects", so it is not possible to refuse to compile the line code, it is also illegal to change the const value. If a base class declares the copy assignment operator private, the compiler also refuses to produce a copy assignment operator for its derived class. Because the compiler generates a copy assignment operator for the derived class, imagining that it can handle the base class component is not possible.

Article 06: If you do not want to use the compiler automatically generated functions, you should explicitly deny

All compiler-generated functions are public, so to prevent copy constructors and copy assignment operators from being generated, you need to declare them yourself. Here are two ways to block copying.

(1) the member function is declared private and deliberately not defined, so that the copy can be blocked. For example: the copy constructor and copy assignment in the iostream library are declared private.

Classpublic:     ... Private :     ...     Homeforsale (const homeforsale&);            //     operator= (const homeforsale&);};

Description: When the client attempts to copy the object, the compiler will block him. When a member function or a friend function copies an object, the connector blocks it.

(2) It is possible to move the connector error to the compiler, and it is good to detect the problem sooner. As long as the copy constructor and the copy assignment operator are declared private and exist in the base class designed specifically to prevent copying actions.

classuncopyable {protected://Allow constructionUncopyable () {}//and destruction of~uncopyable () {}//derived Objects ...Private: Uncopyable (Constuncopyable&);//... but prevent copyinguncopyable&operator=(Constuncopyable&); };

Then let the class inherit uncopyable so that when anyone includes a member function or a friend function attempting to copy an object, the compiler tries to generate a copy constructor and a copy assignment operator, and the compiler build version of the function tries to call its base The corresponding version of class, those calls will be rejected by the compiler.

Note: Uncopyable does not necessarily have to be public to inherit it.

Keep in mind that in order to dismiss a function that the compiler automatically provides, the corresponding member function can be declared private and not implemented. Using a base class like uncopyable is also a practice.

Article 07: Declaring a virtual destructor for a polymorphic base class

C + + explicitly states that when the derived class object is deleted by a base class pointer, and the base class takes a non-virtual destructor, the result is undefined, and the actual execution usually occurs when the derived component of the object is not destroyed.

Description

(1) any class with the virtual function is almost certain that there should be a virtual destructor as well.

(2) If class does not contain a destructor, it usually means that it is not intended to be used as a base class. When class does not attempt to be treated as a base class, making its destructor virtual is often a bad idea. To illustrate:

class //              Public: point (int int ycoord);  ~ Point(); Private :      int x, y;};

If int is 32bit, then the point object can be placed into the 64bit cache. However, when the destructor for point is virtual:

To implement the virtual function, the object must carry some information to determine which virtual function should be called at run time. This information is usually indicated by the VPTR (virtual table pointer) pointer. Vptr points to an array of function pointers, called VTBL (virtual table). Each class with the virtual function has a corresponding VTBL. When an object calls a virtual function, the actual function that is called depends on the VTBL that the object refers to, and the compiler looks for the appropriate function pointer in the VPTR.

If the point class contains the virtual function, the object's volume will increase. Two int plus the size of the vptr pointer. objects can no longer be placed into the 64bit cache, and the C + + point object is no longer structured in the same way as other languages (such as C) because objects in other languages are not vptr and therefore cannot be passed to functions written in other languages. Unless you specifically compensate for the vptr, it also loses portability.

Note: destructors for standard library string,stl containers are all non-virtual, so you cannot inherit them, otherwise undefined behavior may occur.

It is also good to have class with a pure virtual destructor. Suppose you need a pure class, but you don't have a pure virtual function on hand. Because abstract class is always intended to be a base class, and because the base class should have a virtual destructor.

Classpublic:     virtual0;}; Awov::~Awov () {}

You must provide a definition for this pure virtual destructor: The compiler will create a call action to ~awov () in the destructor of Awov's derived class, so if you don't define it, the connector will report an error.

Please remember:

(1) not all base class designs are intended for polymorphic purposes. The base class with polymorphic uses should declare a virtual destructor. If class has any virtual functions, it should have a virtual destructor.

(2)class is designed to not declare a virtual destructor if it is not used as a base class, or if it is not for polymorphism.

Article 08: Don't let exceptions escape destructors

C + + does not prohibit the destructor from spitting out the exception, but it does not encourage you to do so. Consider one of the following examples:

class dbconnection{public:    static  DBConnection Create ();     void close ();}; class dbconn{public:    ~dbconn ()    {        db.close ();    } Private :    DBConnection db;};

It allows the client to program like this without forgetting to call the close function to close the database connection.

{    dbconn DBC (Dbconnection::create ()); ...}

As long as you can successfully call close, if the call causes an exception, the Dbconn destructor propagates the exception, allowing it to leave the destructor. There are two ways to avoid:

(1) if close throws an exception, the program ends. Usually done by abort:

dbconn::~dbconn () {     try  {db.close ();}      Catch  (...)     {         std::abort ();    }}

Forcing the end of a program is a reasonable option if the program encounters an error that occurs between the destructors and cannot continue execution. Because it prevents exceptions from being propagated out of the destructor (which leads to undefined behavior), abort can preempt "ambiguous" behavior to death.

(2) Swallow the exception that occurs because of the call to close

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

Although swallowing an exception is a bad idea, sometimes it is better than a hasty end to the procedure or the risk of unclear behavior.

Neither of these methods can respond to situations that cause close to throw an exception. A better strategy is to redesign the Dbconn interface and provide a close function that is called by the destructor if the client does not actively call the close function.

classdbconn{ Public:    ~dbconn () {if(!closed) {            Try{db.close (); }            Catch (...) {                //make a running record and write down the call to close failed            }        }    }    voidClose () {db.close (); Closed=true; }Private: DBConnection db; BOOLclosed;};

The responsibility for calling close is transferred from the Dbconn destructor to the customer's hand while the Dbconn destructor contains a layer of double insurance. If an operation may throw an exception on failure, and there is a need to handle the exception, the exception must come from a function other than the destructor. Because the destructor throws out the anomaly is dangerous, it always leads to the risk of "prematurely ending the program" or "ambiguous behavior occurring".

Please remember:

(1) the destructor must never spit out an exception. If a function called by a destructor might throw an exception, the destructor should catch any exceptions and then swallow them (not propagate) or end the program.

(2) if the customer needs to react to an exception that is thrown during the operation of an action function, then class should provide a normal function (rather than a destructor) to perform the operation.

Effective C + + 2nd structure/destructor/assignment operation (1)-Reading notes

Related Article

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.