Valid tive C ++ Reading Notes (terms 11-17), effective11-17
Continue the previous article...
(2). constructor/destructor/value assignment
____________________________________________________________________________________________________________________________________
Clause 11: handle "self-assignment" in operator ="
#1. Ensure that operator = has good behavior when the object is assigned a value. These include "self-assigned security" and
"Abnormal security": self-assigned security can be tested through "src object" and "dest object" address comparison ".
And "exception Security" can be achieved through carefully arranged statements, such:
Widget& Widget::operator=(const Widget& rhs){ Bitmap* pOrig= pb; pb = new Bitmap(*rhs.pb); delete pOrig; return *this;}
Because the "self-assignment" test will increase the original and target codes and introduce the control flow, if
When the probability of "self-assignment" is low, introducing the same test will reduce the efficiency of operator =.
The same test should not be introduced.
In addition, the copy-and-swap Technology is also a solution for "self-assignment.
#2. Determine if any function operates on more than one object, and multiple objects are the same object
The behavior is still correct.
____________________________________________________________________________________________________________________________________
Clause 12: Do not forget every component of an object when copying it.
#1. When writing a copying function (copy constructor or copy assignment), make sure that:
(1). Copy all local member variables. (2) Call the appropriate copying function in all base classes.
#2. Do not use the copy constructor to call the copy assignment function, or use the copy assignment function
To call the copy constructor, you should put the common functions into the third function for the two copying functions to call,
This function is usually named init.
____________________________________________________________________________________________________________________________________
(3). Resource Management
____________________________________________________________________________________________________________________________________
Clause 13: object-oriented resource management
#1. To prevent Resource leakage, use the RAII object (Resource acquisition is initialization ),
They obtain resources in the constructor and release resources in the destructor.
Reason: Consider the following functions:
Void f () {while (somecase) {Investment * pInv = createInvestment (); // createInvestment () is a factory function, and pInv is a base class pointer pointing to a derived class object... delete pInv ;}}
If there is a return statement in..., similarly, if there is a continue or goto statement in..., it will cause the program
Early exit without "delete pInv", which will lead to memory leakage. The RAII object is designed to solve this problem.
This problem exists.
(Careful coding can avoid this situation, but during program maintenance, because I do not know the resource management policy, encoding
Personnel may mistakenly add return, continue or goto in..., which leads to this situation .)
#2. Ensure that the management object is immediately put into the resource after obtaining the resource. The interface separation increases the risk of resource leakage.
(It is very likely that an exception is thrown during the separation)
#3. The two commonly used RAII classes are tr1: shared_ptr and auto_ptr. The former is usually
Better choice because its copy behavior is more intuitive and RCSP (reference-counting smart pointer ).
If auto_ptr is selected, the copy Action directs the management resource of the copied RAII to null.
Two instances:
//Investment* createInvestment();std::tr1::shared_ptr<Investment> pInv(createInvestment());std::auto_ptr<Investment> pInv(createInvestment());
#4. tr1: Both shared_ptr and auto_ptr perform delete instead of delete [] in the destructor, which means
Do not use the dynamically allocated array on them. If you have to do so, consider the boost library's
Boost: scoped_array and boost: shared_array classes.
____________________________________________________________________________________________________________________________________
Clause 14: copying actions in resource management
#1. Because the resource managed by the RAII object is a member variable of the RAII object
The copying behavior determines the copying behavior of the RAII object.
#2. Common and common RAII class copying behaviors include: copying is prohibited and reference counting is implemented,
In-depth copying of underlying resources, transferring ownership of underlying resources, etc.
Copying prohibited:
class Lock:private Uncopyable{public: ...}
Reference counting:
Void lock (Mutex * pm); void unlock (Mutex * pm); class Lock {public: explicit Lock (Mutex * pm): // initialize shared_ptr, mutexPtr (pm, unlock) // and use unlock as the delete device {lock (mutexPtr. get ();} private: std: tr1: shared_ptr <Mutex> mutexPtr ;}
When class Lock copying occurs, it will copy mutexPtr, increase the reference count, and call the Compiler
The mutexPtr destructor is called to reduce the reference count. When the reference count is 0
The unlock () operator is called to unlock the Mutex.
Copy the bottom Resource:
Similar to the standard string std: string, a pointer contained in the string is copied, and it points
Heap memory.
Transfer bottom resource ownership:
Class Lock {public: explicit Lock (Mutex * pm): // use Mutex to initialize auto_ptr mutexPtr (pm) {lock (mutexPtr. get ();} private: std: auto_ptr <Mutex> mutexPtr ;}
____________________________________________________________________________________________________________________________________
Clause 15: Provide access to original resources in resource management
#1. APIs usually requires access to raw resources, so every RAII class should provide
A method for obtaining the resources it manages.
#2. Access to the original resource may be converted by display conversion or implicit conversion. In general, the display conversion is safer,
However, implicit conversion is more convenient for customers.
Class Font {public: explicit Font (FontHandle fh): f (fh ){}... fontHandle get () const {return f;} // display and convert operator FontHandle () const {return f;} // implicitly convert private: FontHandle f ;}
____________________________________________________________________________________________________________________________________
Clause 16: The new and delete pairs must be in the same format.
#1. If you use [] in new, you must also use [] in the corresponding delete expression. If you are in
[] Is not used in the expression. Do not use [] in the corresponding delete expression.
#2. When you use new, the memory will be allocated (through operator new ).
(Or multiple) constructors are called (custom data types ). When you use delete
One (or more) destructor is called (custom data type), and the memory is released.
(Via operator delete ).
#3. When new [] is used, a memory unit of "array size record" in the memory will be allocated.
When you delete [], you can specify the size of the object array. For Some compilers, it will
Memory units are recorded as "array size records ".
____________________________________________________________________________________________________________________________________
Article 17: Insert a newed object into a smart pointer using an independent statement
#1. Store the newed object in a smart pointer using an independent statement. If this is not done, once an exception occurs
Thrown, which may cause imperceptible resource leaks.
For example:
processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());
For the C ++ compiler, the new Widget occurs before the tr1: shared_ptr constructor,
However, the execution of the priority () function is unknown, considering that it is in the second place, such:
1. Execute "new Widget"
2. priority () call
3. tr1: shared_ptr constructor call
If an exception is thrown during the call of priority (), the pointer returned by the new Widget is lost without being placed.
Tr1: shared_ptr, which exists for resource memory management,
The program code separation should be described as follows:
std::tr1::shared_ptr<Widget> pw(new Widget);processWidget(pw, priority());
This ensures that the execution sequence selected by the compiler is in the new Widget and tr1: shared_ptr constructor.
Is closely linked to solve the problem of resource leakage.
____________________________________________________________________________________________________________________________________