Effective c++.md

Specification

  • Template and generic programing not marked(40-47)
  • Design and implememt need more code experience to understand
  • Effective c++ need read more than one times
  • Learning by code

Item1 default constructor:

called with no arguments
has no parameter or default value for every parameter.
default constructer should be ‘explicit’ to avoid ‘implicit type conversion’
‘copy instructor’:initialize an object with a different objrect of the same type.
‘copy assignment operator’: copy the value from one object to another of the same type.
‘object passed by value’ in the way of ‘copy construtor’

Rules for effective c++ programming vary,depending on the part of c++ you are using :C OOP Template STL

Item2 Prefer const ,enum,and inline to #define

const not many copy like #define and can be private.
enum can be referenced but #define cann`t
For simple constants ,prefer const objects to #define
For function-like macros, prefer inline function to #define.

Item3 Use const whenever possible

whenever it`s true ,to do so -const.
for pointer ,you can specify whether the pointer itself is const ,the data it point to is const,both or neither.

1
2
3
4
5
6
7
8
char *p = greeting;// non-const pointer,
// non-const data
const char *p = greeting;// non-const pointer,
// const data
char * const p = greeting;// const pointer,
// non-const data
const char * const p = greeting;// const pointer,
// const data

for iterator , const iterator is the iterator itself is const , but const_iterator , the object it point to ia const
const member function make it possible to work with const object.
return in c++ is return a copy of the parameter not itself,which invoked a copy constructor

Declaring something const helps complier detect usage errors and can be applied to objects at any scope. $ compiler enforce bitwise constness but you should program using logical constness. $ when const and non-const member function have essentialy identical implementions, code duplication can be avoided by having the non-const version call the const version.

Item4 Make sure object initialized before used

make sure that all construtors initialize everything in ht eobject.
data members that are const or are reference must be initialzied and can not be assignment.

construtor Destructor and assignmentOperation

Item5: know what function c++ silently writes and calls

Item6: Explicitly disallow the use of compiler-generated functions you do not want.

make the function you don`t want be private in the base class.
To disallow functionality provided by cpmlilers, declare the corresponding member function ‘private’ and give no imlementations.

Item7: Declare destructors virtual in plomorphic base classes.

Give the base class a virtual destructor then deleting a derived class object will do exactly what you want.
a class not intended to be a base class should not have a virtual funtion.

Item8: Prevent exception from leaving destructors

  1. Destructors should never emit exceptions. if functions called in a destructor may throw,the destructor should catch ant exceptions, then swallow them ot terminate the program.
  2. if a class clients need to be able to react to exceptions thrown during an operation, the class should provide a regular function that performs the operation.

Item9 :Never call virtual function during constructor or destructor

Item10: Have assignment operators return a reference to *this

‘x=y=z=15, thus x=15,y=15,z=15’
the way is implemented is that assignment returns a reference to its left-hand arguement.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Widget {
public:
...
Widget& operator+=(const Widget& rhs)
{
...
return *this;
}
Widget& operator=(int rhs)
{
...
return *this;
}
...
};

Item11: Handle assignment to self in operator=

1
2
3
4
5
6
7
8
Widget& Widget::operator=(const Widget& rhs)
{
if (this == &rhs) return *this;
// identity test: if a self-assignment,do nothing
delete pb;
pb = new Bitmap(*rhs.pb);
return *this;
}

if the ‘new’ failed, pb will pointer to an undefined address.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
Widget& Widget::operator=(const Widget& rhs)
{
Bitmap *pOrig = pb; // remember original pb
pb = new Bitmap(*rhs.pb); // point pb to a copy of rhs’s bitmap
delete pOrig; // delete the original pb
return *this;
//$$$ be careful not to delete pa untill after we`re copied what it point to.
}
Widget& Widget::operator=(const Widget& rhs)
{
Widget temp(rhs);// make a copy of rhs’s data
swap(temp); // swap *this’s data with the copy’s
return *this;
}
Widget& Widget::operator=(Widget rhs) // rhs is a copy of the object passed in — note pass by val
{
swap(rhs); // swap *this’s data with
return *this;
}
```
**Make sure any funtion operating on more than one object behave corectly if two or more of the objects are the same.**
#### Item12: COpy all parts of an object
> for derived class, the copy function should not only copy the data member it defined for itself, but also the data member it inherient from the base class,which will be initialized by the constructor that takes no arguements of the base class.
Copy all aparts:
$ copy all local data members
$ invoke the appropriate copying funtion in the base class.
**Don`t try to implement one of the copy constructor funtions in terms of the other 'put common funtionality in a third funtion that both call'**
### Reource Management
#### Item 13:Use objects to manage resources
$ put resource inside an object whose destructor will automatically release the resource when control leaves.
> **Uing Object to Manage Resources**
$ resource are acquired and immediately turned over to resource-manageging abjects.
$ Resource-managing objects use their destructors to ensure that resource are released.
'auto_ptr automaticallt dlete what it point to when the auto_ptr is destroyed, it`s impotantly that there never be more than one auto_ptr pointing to an object'
auto_ptr have anusual characteristic: copy it (via copy constructor or copy assignment operator)and set it null.
'auto_ptr<type>p2=p1 //p1 pointe to null and p2 pointto the object p1 point to'
a reference -counting smart pointer: keep track of how many objects point to aaprticular resource and automaticallt delete the resource when nobady is pointing to it ang longer.
**Both auto_ptr and tr1::shared_ptr use delete in their destructors, not delete []. That means that using auto_ptr or tr1::shared_ptr with dynamically allocated arrays is a bad idea**
#### Item14: Think carefully about copying behavior in resource-managing classes
> $ Peohabit copying:
declare the copt operations private
$ Referene-count the underlying resource:
use the tr1::shared_ptr. define your deleter function
$ Copy the underlying resource:
make sure all the copy released when nessary
$ Transfer ownership of the underlying resource
using auto_ptr
#### Item15 Provide access to raw resource in resource-managing classes $$$$
> shared_ptr and auto_ptr both offer a get member function to perform an explicit conversion :return (a copy of)the raw pointer inside the smart pointer object '.get()'
$ APIs often require access to raw resources ,so each RAII class should offer a way to get at rhe resource it manages.
#### Item16 Use the same form in corresponding *uses* of new and *delete*
> if you use [] in a new expression, you must use [] in the corresponding delete expression
#### Item17 Store newed objects in smart pointers standalone statements.
> 'processWidget(std::tr1::shared_ptr<Widget>(new Widget), priority());' **not good**
'std::tr1::shared_ptr<Widget> pw(new Widget);
processWidget(pw, priority());' // **well**
**Store new ed objects in smart pointers in standalone statements. Failure to do this can lead to subtle resource leaks when exceptions are thrown.**
### Designs ad Declarations
#### Item18 Make interface easy to use correctly and hard to use incorrectly.
> for your class and struct operation, when in doubts, do as the ints do.
tr1::shared_ptr supports custom deleters. This prevents the cross-DLL problem, can be used to automatically unlock mutexes (see Item 14), etc.
#### Treat class design as type design
> ■ How should objects of your new type be created and destroyed?
How this is done influences the design of your class’s
constructors and destructor, as well as its memory allocation and deallocation functions ( operator new , operator new[] , operator delete ,and operator delete[] — see Chapter 8), if you write them.
> ■ How should object initialization differ from object assignment?
The answer to this question determines the behavior of and the differences between your constructors and your assignment operators. It’s important not to confuse initialization with assignment, because they correspond to different function calls (see Item 4).
> ■ What does it mean for objects of your new type to be passedby value?
Remember, the copy constructor defines how pass-by-value is implemented for a type.
> ■ What are the restrictions on legal values for your new type?
Usually, only some combinations of values for a class’s data members are valid. Those combinations determine the invariants your class will have to maintain. The invariants determine the errorchecking you’ll have to do inside your member functions, espe-
cially your constructors, assignment operators, and “setter” functions. It may also affect the exceptions your functions throw and,on the off chance you use them, your functions’ exception specifications.
> ■ Does your new type fit into an inheritance graph?
If you inherit from existing classes, you are constrained by the design of those classes, particularly by whether their functions are virtual or nonvirtual (see Items 34 and 36). If you wish to allow other classes to inherit from your class, that affects whether the functions you declare are virtual, especially your destructor (see Item 7).
> ■ What kind of type conversions are allowed for your new type?
Your type exists in a sea of other types, so should there be conversions between your type and other types? If you wish to allow objects of type T1 to be implicitly converted into objects of type T2 ,you will want to write either a type conversion function in class T1(e.g., operator T2 ) or a non- explicit constructor in class T2 that can be called with a single argument. If you wish to allow explicit conversions only, you’ll want to write functions to perform the conversions, but you’ll need to avoid making them type conversion operators or non- explicit constructors that can be called with one argument. (For an example of both implicit and explicit conversion functions, see Item 15.)
> ■ What operators and functions make sense for the new type?
The answer to this question determines which functions you’ll declare for your class. Some functions will be member functions, but
some will not (see Items 23, 24, and 46).
> ■ What standard functions should be disallowed?
Those are the ones you’ll need to declare private (see Item 6).
> ■ Who should have access to the members of your new type?
This question helps you determine which members are public, which are protected, and which are private. It also helps you de-
termine which classes and/or functions should be friends, as well as whether it makes sense to nest one class inside another.
> ■ What is the “undeclared interface” of your new type?
What kind of guarantees does it offer with respect to performance, exception safety (see Item 29), and resource usage (e.g., locks and
dynamic memory)? The guarantees you offer in these areas will impose constraints on your class implementation.
> ■ How general is your new type?
Perhaps you’re not really defining a new type. Perhaps you’re defining a whole family of types. If so,
you don’t want to define a new class, you want to define a new class template.
> ■Is a new type really what you need? If you’re defining a new de-rived class only so you can add functionality to an existing class,perhaps you’d better achieve your goals by simply defining one or more non-member functions or templates.
#### Item20 Prefer pass-by-reference-to-const to pass-by-value
> ✦ Prefer pass-by-reference-to- const over pass-by-value. It’s typically more efficient and it avoids the slicing problem.
✦ The rule doesn’t apply to built-in types and STL iterator and function object types. For them, pass-by-value is usually appropriate.
#### Item21 Don't try to return a refernece when you must return an object.$$
>
any function returning a reference to a local object is broken as well as a pointer to local object.
???
#### Item22 Declare dta members private.
> Declare data members private . It gives clients syntactically uniform access to data, affords fine-grained access control, allows invariants to be enforced, and offers class authors implementation flexibility
#### Item23 Prefer none-member non-friend functions to member functions.
#### Item24 Declare non-member function when type conversion should apply to all parameters.
> make operator* a non-member function, thus allowing compilers to perform implicit type conversions on all arguments
Whenever you canmavoid friend functions, you should, because, much as in real life,friends are often more trouble than they’re worth
$ If you need type conversions on all parameters to a function (including the one that would otherwise be pointed to by the this pointer),the function must be a non-member
#### Item25 Consider suport for a non-throwing swap $$$
* Swap in STL

namespace std
{
template
void swap(T& a, T& b)
{
T temp(a);
a = b;
b = temp;
}
}

  • swap in pointer the type must support copy constructor and copy assignment
    1
    Not swap the object itself which is so ineffcient,but swap the pointer.

template<>
void swap(Widget& a,Widget& b)
{
swap(a.pImpl, b.pImpl);
}

  • When you want to “partially specialize” a function template, the usual approach is to simply add an overload

Implementions

Item26: Positive varible definitions as long as possible

for variable to use in a loop ,define it out of the loop may be more effecient

Item27 Minimize casting

c++ style casting

const_cast( expression ): cast const object to non-object
dynamic_cast( expression ): safe downcasting
reinterpret_cast( expression )
static_cast( expression ): implicit concersion
✦ Avoid casts whenever practical, especially dynamic_cast s in performance-sensitive code. If a design requires casting, try to develop a cast-free alternative.
✦ When casting is necessary, try to hide it inside a function. Clients can then call the function instead of putting casts in their own code.
✦ Prefer C++-style casts to old-style casts. They are easier to see, and they are more specific about what they do.

Item28 Avoid returning “handles” to object internals

Item29 Strive for exception-safe code $$

Exception-safe functions leak no resources and allow no data structures to become corrupted, even when exceptions are thrown. Such functions offer the basic, strong, or nothrow guarantees.
✦ The strong guarantee can often be implemented via copy-and- swap ,but the strong guarantee is not practical for all functions.
✦ A function can usually offer a guarantee no stronger than the weakest guarantee of the functions it calls.

Item30 Understand the ins and outs of inlineing $$

inline in most c++ programs ia a compile-time activity.
inline functions typically be in header files
limit most inlineing to small as possible
Dont`t declare function template inlne just because they appear in header files

Item31 MInimize complication dependence between files

  1. Avoid using objects when object reference and pointer will do
  2. Depend on class declaraton instead of class definitions whenever you can
  3. Provide aeperate header files for declarations and definition

Inheritence and object-oriented design

Item32 Make sure public ingeritence model “is a”

Everythings that applies to base class must also apply to the derived class ,because every derived class object is a base class object.

Item 33 Avoid hiding inheriented names.

the scope of a derived class is nested inside its base class`s scope.
the same name member funtion in derived class will hide the member funtion with the same name inthe base class ,even if the parameter is different, regaedless of whether the funtions are virtual or non-virtual.

  • if you use pubic inheritence ,you can`t inherit the overloads.
    pubic derived allow to override c+ + `s default hiding of inherited names
    *using base:: functionname;
    make all things in base named functionname visible in derived class, andd the c++ scope search will find the most appropriate member funtion between tha base class function and derived class member function with the same name

Things to Remember

  • Names in derived classes hide names in base classes. Under public inheritance, this is never desirable.
  • To make hidden names visible again, employ using declarations or forwarding functions.**

item34 Differentiate betwwen inhertance of interface and inheritance of impletention

  1. derived class inherit only the interface(declaration):interface only
  2. derived class inherit both the inteface and the implement, but may be overrided the implemention:interface and a default implementation
  3. derived class inherit both the inteface and the implement, but without override anything:inteface and a mandatory implementation
  • pure virtual function
    $ must be redeclared in any derived class
    $ derived class inherit a function interface only.
  • simple virtual function
    $ derived class inherit the interface
    $ the implementation derived can be overrided
    $ if it`s not overrided , call the default implementation in the base class
  • non-virtual function
    $ inteface and a mandatory implementation
    Member function interface are always inherited

Item35 Consider alternatives to virtual functions.

  1. Design Pattern : Template Method call private virtual function through public non-virtual member functions ‘??’
  2. The Strategy Pattern via Function Pointers

  3. The Strategy Pattern via tr1::function

  4. The “Classic” Strategy Pattern

  • Use the non-virtual interface idiom (NVI idiom), a form of the Template Method design pattern that wraps public non-virtual member functions around less accessible virtual functions.
  • Replace virtual functions with function pointer data members, a stripped-down manifestation of the Strategy design pattern.
  • Replace virtual functions with tr1::function data members, thus allowing use of any callable entity with a signature compatible with what you need. This, too, is a form of the Strategy design pattern.
  • Replace virtual functions in one hierarchy with virtual functions in another hierarchy. This is the conventional implementation of the Strategy design pattern.

Item36 Never redifine an inherited non_virtual function

non-virtual function is statically bound, but virtual funtion are dynamically bound
refifine a non-virtual function will make the compiler exhaust.

Item37 Never redefine a function’s inherited default parameter value

virtual function are dynamically bound, but default parameter values are statically bound
all the derived function will inherit the defualt parameter.

Item38 Model “has a” or “is-implemented -in-terms-of”through composition $

  • Composition has meanings completely different from that of public inheritance.
  • In the application domain, composition means has-a. In the implementation domain, it means is-implemented-in-terms-of.

Item 39 Uasage private inheritance judiciously $$

  1. can not convert a derived class object into abase class object if the inheritence relationship id private
  2. members inheriente from the base class will be private member of the derived class.
  3. private inheritance means only software implementation
  • Private inheritance means is-implemented-in-terms of. It’s usually inferior to composition, but it makes sense when a derived class needs access to protected base class members or needs to redefine inherited virtual functions.
  • Unlike composition, private inheritance can enable the empty base optimization. This can be important for library developers who strive to minimize object sizes.

####Item 40 Uasage multiple inheritance judiciously $$

  • Multiple inheritance is more complex than single inheritance. It can lead to new ambiguity issues and to the need for virtual inheritance.
  • Virtual inheritance imposes costs in size, speed, and complexity of initialization and assignment. It’s most practical when virtual base classes have no data.
  • Multiple inheritance does have legitimate uses. One scenario involves combining public inheritance from an Interface class with private inheritance from a class that helps with implementation.

Templates and Generic Programming $$

Item41 Understand implicit interfaces and compile-time polymorphism.

  • Both classes and templates support interfaces and polymorphism.
  • For classes, interfaces are explicit and centered on function signatures. Polymorphism occurs at runtime through virtual functions.
  • For template parameters, interfaces are implicit and based on valid expressions. Polymorphism occurs during compilation through template instantiation and function overloading resolution.

Item 42: Understand the two meanings of typename.

The general rule is simple: anytime you refer to a nested dependent type name in a template, you must immediately precede it by the word typename .

  • When declaring template parameters, class and typename are interchangeable.
  • Use typename to identify nested dependent type names, except in base class lists or as a base class identifier in a member initialization list.

Item43: Know how to access names in templatized base classes.