Valid tive C ++ 55 13-25 notes

Source: Internet
Author: User

Clause 13: object-oriented resource management

1. To prevent resource leakage, use raiI objects to obtain resources in the constructor and release resources in the destructor.

2. Two commonly used raiI classes: tr1: shared_ptr and auto_ptr. The latter copy will point the replicated object to null.

 

RaiI (resource acquisition is initialization): the time when a resource is obtained is the initialization time ------ manage resources with objects.

Auto_ptr: Multiple auto_ptr entries cannot be directed to the same object. Otherwise, the object will be deleted multiple times and undefined. Therefore, if you copy them through the copy constructor or the copy assignment operator, they will become null, And the copied pointer will obtain the unique ownership of the resource.
1 Investment * createinvestment ();
2 void F (){
3 STD: auto_ptr <investment> pinv1 (createinvestment ());
4 STD: auto_ptr <investment> pinv2 (pinv1); // pinv2 points to the object, and pinv1 is null
5 pinv1 = pinv2; // pinv1 points to the object. pinv2 is null.
6}

Because STL containers require that elements have "normal" replication behaviors, these containers cannot accommodate auto_ptr.

Auto_ptr alternative: rcsp (reference-counting smart pointer) references the counting smart pointer. Tracks the total number of objects that point to a resource. When no one points to a resource, the resource is automatically deleted. Ring references cannot be broken.

Tr1: shared_ptr: it is an rcsp and the replication behavior is normal. Therefore, it can be used in STL containers.
1 Investment * createinvestment ();
2 void F (){
3 STD: tr1: shared_ptr <investment> pinv1 (createinvestment ());
4 STD: tr1: shared_ptr <investment> pinv2 (pinv1); // both pinv1 and pinv2 point to the same object.
5 pinv1 = pinv2; // both pinv1 and pinv2 point to the same object.
6}

Auto_ptr and tr1: shared_ptr perform the delete rather than Delete [] action in the destructor. Therefore, using auto_ptr and tr1_1__ptr in the Dynamic Allocation array is an error, but the compilation can still pass.
1 // all use the incorrect Delete format
2 ATD: auto_ptr <STD: String> APS (new STD: String [10]);
3 STD: tr1: shared_ptr <int> SP1 (New int [1024]);

Vecotr and string can almost replace the dynamically allocated array. Boost: scoped_array and boost: shared_array also provide the required behavior.

 

Clause 14: copying behavior in Primary and Secondary School of resource management

1. Forbidden copy: Clause 06: copying operation declaration is private, private inherits uncopyable class

2. The reference count: r1: shared_ptr allows you to specify the deleteer (function or function object). It is called when the number of references is 0. It is a dispensable second parameter.
01 class lock {
02 public:
03 explicit lock (mutex * pm)
04: mutexptr (PM, unlock) // use unlock as the deleteer
05 {
06 lock (mutexptr. Get ());
07} // do not declare the destructor. The default destructor automatically calls the destructor of other non-static member variables.
08 PRIVATE:
09 STD: tr1: shared_ptr <mutex> mutexptr;
10 };

 

Clause 15: Provide access to original resources in resource management

Auto_ptr and tr1: shared_ptr both provide a get member function to execute the display conversion and return the internal original pointer. Operator-> and operator * operators are also overloaded.

It can also provide implicit conversion from the smart with the original pointer, operator orig_ptr_type () const {return orig_ptr ;}

 

Clause 16: The New and delete pairs must take the same form.

If [] is used in the new expression, [] must be used in the corresponding Delete expression. If [] is not used in the new expression, do not use [] in the corresponding Delete expression.

When there are multiple constructors in the class and the memory is dynamically allocated, be careful that all constructors use the same form of new to initialize the pointer.

Do not perform typedef operations on arrays. Use templates such as vector and string.

Because the memory layout of a single object is generally different from that of an array. Most compilers usually have records of the array size for the memory layout of arrays. Using [], the compiler can know whether there is an array size record.

 

Article 17: Insert a newed object into a smart pointer using an independent statement
1 int priority ();
2 void processwidget (STD: tr1: shared_ptr <widget> PW, int priority );
3
4 processwidget (new widget, priority (); // cannot be compiled
5
6 processwidget (STD: tr1: shared_ptr <widget> (new widget), priority (); // It can be compiled, but the exception is not safe. If priority () an exception is thrown between new and shared_ptr.
7
8 STD: tr1: shared_ptr <widget> Pw (new widget );
1 processwidget (PW, priority (); // OK

 

 

Article 18: Make the interface easy to use and misuse

1. Maintain consistency between interfaces and built-in types of behavior.

2. tr1: shared_ptr supports custom delimiters (custom deleter ). This prevents cross-DLL problem and can be used to automatically unlock mutex locks.
01 class Date {
02 public:
03 date (INT month, int day, int year );
04 };
05 date D (30, 3, 1995 );//
06
07 // wrapper types
08 struct day {
09 explicit Day (int d): Val (d ){}
10 int val;
11 };
12 struct month {
13 explicit month (INT m): Val (m ){}
14 int val;
15 };
16 struct year {
17 explicit year (INT y): Val (y ){}
18 int val;
19 };
20 class Date {
21 public:
22 date (const month & M, const day & D, const year & Y );
23 };
24 Date D (1995,); // Error
25 date D (month (3), Day (30), Year (1995); // OK, the type is correct
26
27 class month {
28 public:
29 static month Jan () {return month (1 );}
30 static month FEB () {return FEB (2 );}
31...
32 static month Dec () {return month (12 );}
33 private:
34 explicit month (INT m );
35 int month;
36 };
37 date D (month: Mar (), Day (30), Year (1995 ));

 

Returns a smart pointer to the factory function.
1 STD: tr1: shared_ptr <investment> createinvestment ();
2 STD: tr1: shared_ptr <investment> pinv (0, getridofinvetment); // compilation failed
3 STD: tr1: shared_ptr <investment> pinv (static_cats <investment *> (0), getridofinvetment); // OK

 

Cross-DLL problem: the object is new in the DLL and deleted in another DLL, causing a runtime error. tr1: shared_ptr does not.

 

Clause 19: design class is like design type

1. How to create and destroy a New Type object: constructor, destructor, memory allocation and release operator new, operator Delete, operator new [], operator Delete []

2. Differences between object initialization and assignment. Const (reference and const member), value assignment operator

3. What does the new type object passed by value mean? copy constructor

4. What is the valid value of the new type?

5. Do new types need to be combined with an inherited Graph System? Constraint, virtual destructor

6. What type conversion is required for the new type. Non-explicit constructor, operator T2

7. What operators and functions are reasonable for the new type: member functions

8. What kind of standard function should be rejected: It must be declared as private

9. Who should use the new type member: Public protected? Private? Friend? Nested?

10. What is the "undeclared interface" of the new type "? What guarantee does it provide for efficiency, exceptional security, and resource usage?

11. How is the new type generalized? Should I define a class template?

12. Do I really need a new type? If you just define a new derived class to add new features, isn't it better to define one or more non-menber functions or templates? Clause 23.

 

Clause 20: replace pass-by-reference-to-const with pass-by-value.

Except for built-in types, STL iterators, and function objects, all other things shall comply with these terms as much as possible.

The cost of pass-by-value: the copy construction of the form parameter, the copy constructor of the base class (if any) of the form parameter, and the copy constructor of all members of the base class of the form parameter, the copy constructor of all the members of the parameter and the Destructor corresponding to all the constructor.

By-reference can also avoid the slicing problem: the object by-value of the derived class is transmitted to the base class.

 

Clause 21: when an object must be returned, do not think about returning its reference

Do not return a pointer or reference pointing to a local stack object, or return a reference pointing to a heap-allocated object, or return a pointer or reference an object pointing to a local stack, and multiple such objects may be required at the same time.
01 class rational {
02 public:
03 rational (INT Numerator = 0;
04 int Denominator = 1 );
05 PRIVATE:
06 int N, D;
07 friend const rational operator * (const rational & LHS,
08 const rational & RHs );
09 };
10
11 const rational & operator * (const rational & LHS,
12 const rational & RHs ){
13 rational * result = New Rational (LHS. N * RHS. N, LHS. D * RHS. D );
14 return * resual;
15}
16 rational w, x, y, z;
17 W = x * y * z; // two new operations. The pointer Delete is not found, causing memory leakage.
18
19 const rational & operator * (const rational & LHS,
20 const rational & RHs ){
21 static rational result;
22 result = ...;
23 return resual;
24}
25 // static causes multi-thread security problems
26 if (w * X) = (y * z) {} // always true
27 // The operator * does change the value of static rational twice. However, since all the objects returned are references, the caller will always see the present value of static rational.
28
29 inline const rational & operator * (const rational & LHS,
30 const rational & RHs ){
31 return rational (LHS. N * RHS. N, LHS. D * RHS. D );
32} // construct and analyze the composition of the returned values, and the compiler may be optimized.

 

Clause 22: declare member variables as private

1. The statement is private, which allows the customer to access data consistency, subscribe access control, promise constraints to be guaranteed, and provide the class author for full elasticity.

2. Protected is more encapsulated than public.

Encapsulation of something and what may happen when its content changesCodeThe amount of destruction is inversely proportional.

When we remove a public member variable, all the customer codes that use it are corrupted, an unknown large number.

When the protected member variable is removed, all the derived classes that use it are damaged, which is also an unknown large number.

 

Cla23: Native replaces the member function with non-Member and non-friend.

It can increase encapsulation, package elasticity, and function expansion.
01 class webbrowser {
02 public:
03 void upload AchE ();
04 void clearhistory ();
05 void removecookie ();
06
07 void cleareverything (); // call receivache, clearhistory, removecookie
08 };
09
10 // or define the non-member non-friend function. Which one is better?
11 void cleareverything (webbrower & WB ){
12 WB. Sort AchE ();
13 WB. clearhistory ();
14 WB. removecookie ();
15}

 

The more things are encapsulated, the less people can see it. The less people see it, the more elasticity we have and change it. This is the reason we advocate encapsulation First: we change things and only influence limited customers.

The less code we can see the data, the more data is encapsulated, the more we can freely change the object data. Therefore, the more functions access data, the lower the Data encapsulation.

If the data is not private, there is no encapsulation. Only member functions or friend functions can access private.

Therefore, non-member non-friend is more encapsulated than member functions.


01 // If webbrowser has a large number of convenient functions, it can reduce the dependency between compilation of each function.
02 // you only need to include the required header file.
03 // webbrowser. h
04 namespace webbrowserstuff {
05 class webbrowser {...};
06... // core functions, such as non-member functions required by all customers
07}
08
09 // webbrowserbookmark. h
10 namespace webbrowserstuff {
11 .. // convenient functions related to bookmarks
12}
13
14 // webbrowserbookmark. h
15 namespace webbrowserstuff {
16 .. // convenience functions related to cookies
17}

 

Clause 24: If all parameters require type conversion, use the non-member function for this purpose.
01 class rational {
02 public:
03 rational (INT Numerator = 0, int Denominator = 1 );
04 int numerator () const;
05 int denominator () const;
06 PRIVATE :...
07 };
08
09 // operator * should it be implemented as member or non-member? Ignore clause 23
10 // first look at the member implementation
11 class rational {
12 public:
13 const rational operator * (const rational & LHS, const rational & RHs );
14 };
15 rational oneeight (1, 8 );
16 rational onehalf (1, 2 );
17 rational result;
18
19 result = onehalf * 2; // OK, onehalf. Operator * (2); implicit conversion
20 result = 2 * onehalf; // error, 2. Operator * (onehalf );
21
22 class rational {
23...
24 };
25 const rational operator * (const rational & LHS, const rational & RHs ){
26 return rational (LHS. numerator () * RHS. numerator (),
27 LHS. denominator () * RHS. denominator ());
28}
29 // various OK

Clause 25: Write A swap function without throwing an exception.
01 // pimpl (point to implementation) method: points to an object with a pointer containing real data
02 namespace STD {
03 template <typename T>
04 void swap (T & A, T & B ){
05 t temp ();
06 A = B;
07 B = temp;
08}
09}
10
11 class widgetimpl {
12 public:
13...
14 private:
15 int A, B, C; // there may be a lot of data
16 STD: vector <double> V; // indicates that the replication takes a long time.
17 };
18 class widget {
19 public:
20 widgets (const widgets &);
21 widget & operator = (const widget & RHs ){
22 * pimpl = * RHS. pimpl;
23}
24 private:
25 widgetimpl * pimpl;
26 };
27
28 // replace two widget objects. You only need to replace the pimpl pointer. The default swap copies 3 and Widget objects, and three widgetimpl objects, which are inefficient.
29
30 namespace STD {
31 template <>
32 void swap <widget> (widget & A, widget & B ){
33 swap (A. pimpl, B. pimpl); // failed to compile, access private
34}
35} // declare friend ????
36
37 // a policy consistent with STL
38 class widget {
39 public:
40 void swap (widget & Other ){
41 Using STD: swap; // exposure
42 swap (pimpl, other. pimpl); // query order: This namespace-> global scope-> STD: swap special edition (if any)-> STD: swap normal Edition
43}
44 };
45 namespace STD {
46 template <>
47 void swap <widget> (widget & A, widget & B ){
48 A. Swap (B );
49}
50}
51 // if both classes are templates
52 template <typename T> class widgetimpl {...};
53 template <typename T> class widget {...};
54 // The function template cannot be biased. c ++ only supports the biased function template.
55 // you cannot add a new template to the STD namespace. You can only add a fully-specific template.
56 // a solution
57 class widgetstuff {
58... // templated widgetimpl, etc.
59 template <typename T>
60 class widget {...}; // contains the swap member function.
61
62 template <typename T>
63 void swap (widget <t> & A, widget <t> & B ){
64 A. Swap (B );
65}
66 };

 

Summary:

If swap's default version is less efficient (it almost always means that your class goods template uses the pimpl method ):

1. Provide a public swap member function to efficiently replace two object values of your type and avoid throwing an exception (exception security, clause 29)

2. Provide a non-member swap in The namespace where your class or template is located, and ask him to call the above swap member functions

3. If you are writing a class (not a template), you can define STD: swap for your class and have it call your member function.

Finally, use the using expression to expose STD: swap to your function without any namespace modifier.

[Reprint] http://www.cnblogs.com/Atela/archive/2011/04/08/2008859.html

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.