Article 1: Treat C + + as a language federal
C + + consists of these four parts:
L C
L object-oriented C + +
L Template C + +
L STL
N C + + high-efficiency programming code varies depending on what part of C + + you use
clause 2: Replace # define as const,enum,inline as possible
The following macro carries the macro argument and calls the function f:
#define CALL_WITH_MAX (a B) f ((a) > (b)? A):(B))
Even if you take the parentheses for all the real things, look at the unthinkable.
int a=5,b=0;
Call_with_max (++A,B); A is accumulated two times
Call_with_max (++A,B+10)//a is accumulated once
can be changed to the form of an inline function:
Template <class t>
inline void Callwithmax (const t&a,constt&b)
{
f (A>B?A:B);
}
N for simple constants, it is best to replace the # define with a const object or enums
N for macros that resemble functions, it is best to replace the # define with the inline function instead
clause 3: Use const whenever possible
Vector<int> VEC;
Const vector<int>:: Iterator Iter=vec.begin ();
*iter=10; That's right
iter++;//Error
the const member function cannot modify a member variable, but the const member function can also modify its value after the variable is added to the mutable.
Vector<int>:: Const_iterator citer=vec.begin ();
*citer=10; Error
++citer; That's right
class TextBlock
{
Public
Size_tlength () const;
Private
Char *ptext;
mutablestd::size_t textLength;
};
std::size_t ctextblock::length () const
{
Textlength=std::strlen (Ptext); That's right
}
N declaring something as const can help the compiler detect incorrect usage. Const can be applied to objects in any scope, function arguments, function return types, member function ontologies
n when the const and NON-CONST member functions have a substantially equivalent implementation, making the NON-CONST version call the const version avoids code duplication.
Article 4: Determine that an object has been initialized before it is used
class phonenumber{...};
Class Abentry
{
Public
Abentry (conststd::string &name,const std::string &string &address,conststd::list<PhoneNumber> &phones);
Private
Std::stringthename;
std::list<phonenumber>thephones;
intnumtimesconsulted;
};
Abentry::abentry (const std::string&name,const std::string &address,const std::list <PhoneNumber>& Phone
{
Thename=name;
theaddress=address;
Thephones=phones;
Numtimeconsulted=0;
}
The above constructor calls the default constructor before entering the body of the function, and then assigns a value in the function body, which is less efficient and better:
Abentry::abentry (const std::string&name,const std::string &address,const std::list<phonenumber>& Phones): thename (name), theaddress (address), thephones (phones), numtimeconsulted (0)
{}
Member initialization lists are more efficient because each member variable in the initial column is taken as an argument to the constructor of each member variable. Thenames with name as the initial value of the copy construction, theaddress with address as the initial value of the copy construction, thephones to phones as the initial value of the copy construction.
for built-in types, the cost of initialization and assignment is the same, but for consistency, it is initialized in the initialization list.
n manual initialization of built-in type objects because C + + does not guarantee that they are initialized
N constructors are best used with member initial columns, rather than using assignment operations within the constructor body, the initial Value column lists the member variables in the same order as they are declared in class.
Article 5: Understand what functions C + + silently writes and calls
The N compiler secretly creates a default constructor for class, a copy constructor, a copyassignment operator, and a destructor
Article 6: If you do not want to use the compiler automatically generated functions, you should explicitly deny
If a class cannot be copied or copied, the method is to declare the copy constructor and the assignment function as private. This prevents the compiler from generating a default version for it, and prevents people from invoking it.
Article 7: Declaring a virtual destructor for a polymorphic base class
It is false to declare all calsses destructors as virtual, as if they had never been declared as virtual. What many people have learned is that the virtual destructor is declared only if there is at least one virtual function within the class.
n a base class with polymorphic properties should declare a virtual destructor, and if the class has any virtual functions, it should have a virtual destructor.
The N class is not designed to be used as a base class or not to be polymorphic, it is not necessary to declare a sequence destructor.
Article 8: Don't let exceptions escape destructors
A destructor that spits out an exception can cause the program to end prematurely or to appear ambiguous behavior.
n destructors should never throw an exception, and if a function called by a destructor might throw an exception, the destructor should catch any exceptions and then swallow them or end the program.
N if the customer needs to react to an exception thrown during the operation of an action function, the class should provide a normal function to perform the operation.
Article 9: Never call the virtual function in the construction and destruction process
The base class constructor executes much earlier than the derived class constructor, when the base class constructor executes when the member variable of the derived class has not been initialized. If the virtual function that is called during this period drops to the derived class, the function of the derived class uses the local member variable, and these member variables are not initialized.
n Do not call virtual functions during construction and destruction, because such calls never descend to derived classes.
Clause 10: Make operator= return a reference to a *this
Class Widget
{
Public
widget&operator+= (const widgets & RHS)
{
...
Return*this;
}
widget& operator= (int rhs)
{
...
Return*this;
}
};
Article 11: Handling "self-assignment" in operator=
There are class definitions as follows:
Class bitmap{...}
Class Widget
{
...
Private
BITMAP*PB;
};
The following is the implementation code for operator=, which looks reasonable on the surface, but is not safe when self-assignment occurs.
Widgets &
widget::operator= (const Widget &RHS)
{
Delete PB;
Pb=new Bitmap (*THS.PB);
return *this;
}
The problem with the code above is that if you assign a value, the memory of the object is freed. To prevent this error, you can add a test to the assignment operator.
Widgets & widget::operator = (const WIDGET&RHS)
{
if (THIS==RHS)
Return*this;
DELETEPB;
Pb=newbitmap (*RHS.PB);
return *this;
}
The code above is self-assigning safe, but the problem is that it is not guaranteed to be exceptionally secure, because if an exception occurs in new bitmap, the result will be an error.
The following is a self-assigning safe and exceptionally secure code:
Widget &widget:: operator= (const WIDGET&RHS)
{
Bitmap *PORIG=PB;
Pb=new Bitmap (*RHS.PB);
Delete Porig;
return *this;
}
At this point, if new Bitmao throws an exception, PB remains intact, and this code can handle self-assignment.
Article 12: Do not forget every ingredient when copying an object
When you compose a copy function for a derived class, you must carefully assign its base class component. Those components are often private, so you can't access them directly, and you should let the copy function of the derived class call the corresponding base class function.
Prioritycustomer::P rioritycustomer (Constprioritycustomer & RHS): Customer (RHS), priority (Rhs.priority)
{
;
}
prioritycustomer&prioritycustomer::operator = (const prioritycustomer &RHS)
{
Customer::operator= (RHS);
priority=rhs.priority;
return *this;
}
The copy function should ensure that all member variables and all base class components within the object are copied.
Effective C + + reading notes 1