Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
programming:improve-your-cpp [2006/12/14 14:19]
cyril created
programming:improve-your-cpp [2006/12/14 14:47]
cyril
Line 1: Line 1:
 +<php>$conf['maxtoclevel'] = 3;</php>
  
 \\ This page is based on the excellent books __50 ways to improve your C++__ and __35 more ways to improve your C++__. \\ This page is based on the excellent books __50 ways to improve your C++__ and __35 more ways to improve your C++__.
Line 8: Line 8:
  
  
-==== Item 1 : Use const and inline instead of #define ====+=== Item 1 : Use const and inline instead of #define ===
 Because constants don't appear in the symbole table which is annoying for debugging : Because constants don't appear in the symbole table which is annoying for debugging :
-<code c++>+<code cpp>
 const float ASPECT_RATIO = 1.653; const float ASPECT_RATIO = 1.653;
 </code> </code>
 And because there are lot of traps with macros : And because there are lot of traps with macros :
-<code c++>+<code cpp>
 template<class T> inline T& MAX(T& a, T& b) { return a>b ? a : b; } template<class T> inline T& MAX(T& a, T& b) { return a>b ? a : b; }
 </code> </code>
  
-==== Item 2 : Prefer iostream to stdio.h ====+=== Item 2 : Prefer iostream to stdio.h ===
 Because of type safety an extensiblity. To define stream operators in your class : Because of type safety an extensiblity. To define stream operators in your class :
-<code c++>+<code cpp>
 friend ostream& operator<<(ostream& s, const ComplexInt& c); friend ostream& operator<<(ostream& s, const ComplexInt& c);
 ostream& operator<<(ostream& s, const ComplexInt& c) { s << c.r << " " << c.i; return s; } ostream& operator<<(ostream& s, const ComplexInt& c) { s << c.r << " " << c.i; return s; }
 </code> </code>
  
-==== Item 3 : Use new and delete instead of malloc and free ====+=== Item 3 : Use new and delete instead of malloc and free ===
 Because they don't call constructors and destructors !  Because they don't call constructors and destructors ! 
  
-==== Item 4 : Prefer C++-style comments ====+=== Item 4 : Prefer C++-style comments ===
 Because you can't embed C-style comments in other comments ! Because you can't embed C-style comments in other comments !
  
Line 34: Line 34:
 ===== Memory management ===== ===== Memory management =====
  
-==== Item 5 : Use the same form in corresponding calls to new and delete ====+=== Item 5 : Use the same form in corresponding calls to new and delete ===
 ''new'' with ''delete'', and ''new[]'' with ''delete[]'', or memory leaks ! (don't call all destructors) ''new'' with ''delete'', and ''new[]'' with ''delete[]'', or memory leaks ! (don't call all destructors)
  
-==== Item 6 : Call delete on pointer members in destructors ====+=== Item 6 : Call delete on pointer members in destructors ===
 Initialize all pointer members in each of the constructors (at ''NULL'' if not allocated) ;\\ Initialize all pointer members in each of the constructors (at ''NULL'' if not allocated) ;\\
 Delete for all pointer members the existing memory and assign new memory in the assignment operator ; \\ Delete for all pointer members the existing memory and assign new memory in the assignment operator ; \\
Line 43: Line 43:
  
  
-==== Item 7 : Check the return value of new ====+=== Item 7 : Check the return value of new ===
 Set an error-handling function, globally : Set an error-handling function, globally :
-<code c++>+<code cpp>
 void noMoreMemory() { cerr << "Unable to satisfy request for memory\n"; abort(); } void noMoreMemory() { cerr << "Unable to satisfy request for memory\n"; abort(); }
 main() { set_new_handler(noMoreMemory); ... } main() { set_new_handler(noMoreMemory); ... }
 </code> </code>
 Or for a specific class : Or for a specific class :
-<code c++>+<code cpp>
 typedef void (*PEHF)(); //  PEHF = pointer to error handling function typedef void (*PEHF)(); //  PEHF = pointer to error handling function
  
Line 82: Line 82:
  
  
-==== Item 8 : Adhere to convention when writing new ====+=== Item 8 : Adhere to convention when writing new ===
 Means having the right return value (pointer or 0), and calling an error-handling function when insufficient memory is avalaible : Means having the right return value (pointer or 0), and calling an error-handling function when insufficient memory is avalaible :
-<code c++>+<code cpp>
 void * operator new(size_t size) // your operator new could take additional params void * operator new(size_t size) // your operator new could take additional params
 { {
Line 99: Line 99:
 </code> </code>
 If the operator new is in a class X, you should add before to attempt to allocate memory : If the operator new is in a class X, you should add before to attempt to allocate memory :
-<code c++>+<code cpp>
 if (size != sizeof(X)) return ::new char[size]; if (size != sizeof(X)) return ::new char[size];
 </code> </code>
 This occur when you inheritate from the class without rewriting the new operator. This occur when you inheritate from the class without rewriting the new operator.
  
-==== Item 9 : Avoid hiding the global new ====+=== Item 9 : Avoid hiding the global new ===
 If you add parameters to your ''new'' redefinition, it blocks access to the usual form of new, so rewrite also the classical form : If you add parameters to your ''new'' redefinition, it blocks access to the usual form of new, so rewrite also the classical form :
-<code c++>+<code cpp>
 class X class X
 { {
Line 119: Line 119:
 </code> </code>
  
-==== Item 10 : Write delete if you write new ====+=== Item 10 : Write delete if you write new ===
 You can rewrite ''new'' to allocate small objects in a large memory zone (in order to speed up allocations and save memory), but you have also to write ''delete'' ! You can rewrite ''new'' to allocate small objects in a large memory zone (in order to speed up allocations and save memory), but you have also to write ''delete'' !
-<code c++>+<code cpp>
 class Airplane class Airplane
 { {
Line 163: Line 163:
 ===== Constructors, Destructors, and Assignment operators ===== ===== Constructors, Destructors, and Assignment operators =====
  
-==== Item 11 : Define a copy constructor and an assignment operator for classes with dynamically allocated memory ====+=== Item 11 : Define a copy constructor and an assignment operator for classes with dynamically allocated memory ===
  
-==== Item 12 : Prefer initialization to assignment in constructors ====+=== Item 12 : Prefer initialization to assignment in constructors ===
 You don't have choice for constants or reference members, but in general it is more efficient (constructors are always called once, and with initialization all members are written in raw which is faster than assigning them one by one). You don't have choice for constants or reference members, but in general it is more efficient (constructors are always called once, and with initialization all members are written in raw which is faster than assigning them one by one).
  
-==== Item 13 : List members in an initialization list in the order in which they are declared ====+=== Item 13 : List members in an initialization list in the order in which they are declared ===
 Because it is the order of the declarations which is followed by the compiler, not the order of the initialization list, so you can fall into traps if you don't have the same order. Because it is the order of the declarations which is followed by the compiler, not the order of the initialization list, so you can fall into traps if you don't have the same order.
  
-==== Item 14 : Make destructors virtual in base classes ====+=== Item 14 : Make destructors virtual in base classes ===
 Because if you don't, if you create a derived object and put it in a pointer of the base class, when you will delete it it won't call the destructor of the derived class ! But only for base class (if you plan to inheritate from it), which generally corresponds to the fact that there is at least one virtual function, because you loose a little performance. Tip : if you want to have an abstract class, but you don't have any function to make pure virtual, declare a pure virtual destructor ! (but you have nevertheless to provide a definition for this pure virtual destructor, and do not declare it inline because it could have problems with the virtual thing). Because if you don't, if you create a derived object and put it in a pointer of the base class, when you will delete it it won't call the destructor of the derived class ! But only for base class (if you plan to inheritate from it), which generally corresponds to the fact that there is at least one virtual function, because you loose a little performance. Tip : if you want to have an abstract class, but you don't have any function to make pure virtual, declare a pure virtual destructor ! (but you have nevertheless to provide a definition for this pure virtual destructor, and do not declare it inline because it could have problems with the virtual thing).
  
-==== Item 15 : Have operator= return a reference to *this ====+=== Item 15 : Have operator= return a reference to *this ===
 To allow chains assignments : To allow chains assignments :
-<code c++>+<code cpp>
 C& C::operator=(const C&); C& C::operator=(const C&);
 </code> </code>
  
-==== Item 16 : Assign to all data members in operator====+=== Item 16 : Assign to all data members in operator= ===
 Because if you want to assign some, the compiler won't anymore assign the other ones. Moreover if it is a derived class you have also to initialize the data members of the base class :  Because if you want to assign some, the compiler won't anymore assign the other ones. Moreover if it is a derived class you have also to initialize the data members of the base class : 
 <code cpp>((A&) *this = rhs;</code> (if base class doesn't provide = operator) <code cpp>((A&) *this = rhs;</code> (if base class doesn't provide = operator)
 <code cpp>A::operator=(rhs);</code> (if it does) <code cpp>A::operator=(rhs);</code> (if it does)
  
-==== Item 17 : Check for assignment to self in operator====+=== Item 17 : Check for assignment to self in operator= ===
 That's to say, always begin by : ''if (this == &rhs) return *this;''. Not only because it saves time, but above all because it will create serious problems with freeing and reallocating resources ! But be careful this test won't work with multiple inheritance because one same object can have different addresses according to the type it is casted to. If so you could add an unique identifier for each object. That's to say, always begin by : ''if (this == &rhs) return *this;''. Not only because it saves time, but above all because it will create serious problems with freeing and reallocating resources ! But be careful this test won't work with multiple inheritance because one same object can have different addresses according to the type it is casted to. If so you could add an unique identifier for each object.
  
Line 192: Line 192:
  
  
-==== Item 18 : Strive for class interfaces that are complete and minimal ====+=== Item 18 : Strive for class interfaces that are complete and minimal ===
  
-==== Item 19 : Differentiate among member functions, global functions, and friend functions ====+=== Item 19 : Differentiate among member functions, global functions, and friend functions ===
  
-==== Item 20 : Avoid data members in the public interface ====+=== Item 20 : Avoid data members in the public interface ===
  
-==== Item 21 : Use const whenever possible ====+=== Item 21 : Use const whenever possible ===
  
-==== Item 22 :  ====+=== Item 22 :  ===
  
-==== Item 23 :  ====+=== Item 23 :  ===
  
-==== Item 24 :  ====+=== Item 24 :  ===
  
-==== Item 25 :  ====+=== Item 25 :  ===
  
-==== Item 26 :  ====+=== Item 26 :  ===
  
-==== Item 27 :  ====+=== Item 27 :  ===
  
-==== Item 28 :  ====+=== Item 28 :  ===
  
-==== Item 29 :  ====+=== Item 29 :  ===
  
-==== Item 30 :  ====+=== Item 30 :  ===
  
-==== Item 31 :  ====+=== Item 31 :  ===
  
-==== Item 32 :  ====+=== Item 32 :  ===
  
-==== Item 33 :  ====+=== Item 33 :  ===
  
-==== Item 34 :  ====+=== Item 34 :  ===
  
-==== Item 35 :  ====+=== Item 35 :  ===
  
-==== Item 36 :  ====+=== Item 36 :  ===
  
-==== Item 37 :  ====+=== Item 37 :  ===
  
-==== Item 38 :  ====+=== Item 38 :  ===
  
-==== Item 39 :  ====+=== Item 39 :  ===
  
-==== Item 40 :  ====+=== Item 40 :  ===
  
-==== Item 41 :  ====+=== Item 41 :  ===
  
-==== Item 42 :  ====+=== Item 42 :  ===
  
-==== Item 43 :  ====+=== Item 43 :  ===
  
-==== Item 44 :  ====+=== Item 44 :  ===
  
-==== Item 45 :  ====+=== Item 45 :  ===
  
-==== Item 46 :  ====+=== Item 46 :  ===
  
-==== Item 47 :  ====+=== Item 47 :  ===
  
-==== Item 48 :  ====+=== Item 48 :  ===
  
-==== Item 49 :  ====+=== Item 49 :  ===
  
-==== Item 50 :  ====+=== Item 50 :  ===
  
  
Line 262: Line 262:
 ===== Basics ===== ===== Basics =====
  
-==== Item 1 : Distinguish between pointers and references ====+=== Item 1 : Distinguish between pointers and references ===
 References must refer to an object (no null reference), and that's why they must be initialized. Indeed you don't have to check if a reference parameter is null or not, contrary to pointers. But references can't be reassigned to refer to different objects. References must refer to an object (no null reference), and that's why they must be initialized. Indeed you don't have to check if a reference parameter is null or not, contrary to pointers. But references can't be reassigned to refer to different objects.
  
-==== Item 2 : Prefer C++-style casts ====+=== Item 2 : Prefer C++-style casts ===
 Because they are easier to parse (both for humans and tools), and because it can avoid errors.\\ Because they are easier to parse (both for humans and tools), and because it can avoid errors.\\
 ''static_cast<type>(expression)'' : normal cast, for example ''double'' to ''int''.\\ ''static_cast<type>(expression)'' : normal cast, for example ''double'' to ''int''.\\
 ''const_cast'' to cast away the constness or volatileness of an expression :  ''const_cast'' to cast away the constness or volatileness of an expression : 
-<code c++>+<code cpp>
 void update(X *px); void update(X *px);
 const X x; const X x;
Line 276: Line 276:
 ''dynamic_cast'' to perform safe casts down or across an inheritance hierarchy (base to derived objects), and it returns NULL if it fails (or throw an exception when casting references).\\ ''dynamic_cast'' to perform safe casts down or across an inheritance hierarchy (base to derived objects), and it returns NULL if it fails (or throw an exception when casting references).\\
 ''reinterpret_cast'' for implementation-defined casts (rarely portable), for example casting between function pointer types : ''reinterpret_cast'' for implementation-defined casts (rarely portable), for example casting between function pointer types :
-<code c++>+<code cpp>
 typedef void (*FuncPtr)(); // a FuncPtr is a pointer to "void foo()" typedef void (*FuncPtr)(); // a FuncPtr is a pointer to "void foo()"
 FuncPtr funcPtrArray[10]; FuncPtr funcPtrArray[10];
Line 283: Line 283:
 </code> </code>
  
-==== Item 3 : Never treat arrays polymorphically ====+=== Item 3 : Never treat arrays polymorphically ===
 That's to say don't place derived class objects in an array of base class pointers, if they don't have the same size, because indexing will use size of the base class. So problems when you write your loop, or when you delete the array (the compiler generates a loop, and it is said in the language specification that the result is undefined). That's to say don't place derived class objects in an array of base class pointers, if they don't have the same size, because indexing will use size of the base class. So problems when you write your loop, or when you delete the array (the compiler generates a loop, and it is said in the language specification that the result is undefined).
  
-==== Item 4 :  ====+=== Item 4 :  ===
  
 ===== Operators ===== ===== Operators =====
  
-==== Item 5 :  ====+=== Item 5 :  ===
  
-==== Item 6 :  ====+=== Item 6 :  ===
  
-==== Item 7 :  ====+=== Item 7 :  ===
  
-==== Item 8 :  ====+=== Item 8 :  ===
  
 ===== Exceptions ===== ===== Exceptions =====
-==== Item 9 :  ====+=== Item 9 :  ===
  
-==== Item 10 :  ====+=== Item 10 :  ===
  
-==== Item 11 :  ====+=== Item 11 :  ===
  
-==== Item 12 :  ====+=== Item 12 :  ===
  
-==== Item 13 :  ====+=== Item 13 :  ===
  
-==== Item 14 :  ====+=== Item 14 :  ===
  
-==== Item 15 :  ====+=== Item 15 :  ===
  
 ===== Efficiency ===== ===== Efficiency =====
-==== Item 16 :  ====+=== Item 16 :  ===
  
-==== Item 17 :  ====+=== Item 17 :  ===
  
-==== Item 18 :  ====+=== Item 18 :  ===
  
-==== Item 19 :  ====+=== Item 19 :  ===
  
-==== Item 20 :  ====+=== Item 20 :  ===
  
-==== Item 21 :  ====+=== Item 21 :  ===
  
-==== Item 22 :  ====+=== Item 22 :  ===
  
-==== Item 23 :  ====+=== Item 23 :  ===
  
-==== Item 24 : Understand the costs of virtual functions, multiple inheritance, virtual base classes, and RTTI ====+=== Item 24 : Understand the costs of virtual functions, multiple inheritance, virtual base classes, and RTTI ===
  
 Virtual functions works with virtual tables (one per class) containing pointers to functions, and virtual table pointers (one per object) pointing to the good virtual table. Hence it increases size of objects, per-class data, and reduce performance : because of indirections (but that's almost nothing), and mainly because it prevents inlining (except if the function is called from an object and not a pointer or a reference, but that's almost never the case). Virtual functions works with virtual tables (one per class) containing pointers to functions, and virtual table pointers (one per object) pointing to the good virtual table. Hence it increases size of objects, per-class data, and reduce performance : because of indirections (but that's almost nothing), and mainly because it prevents inlining (except if the function is called from an object and not a pointer or a reference, but that's almost never the case).
programming/improve-your-cpp.txt ยท Last modified: 2013/09/19 16:40 (external edit)
CC Attribution-Share Alike 4.0 International
Driven by DokuWiki Recent changes RSS feed Valid CSS Valid XHTML 1.0