C Style Casts C style casts: do not communicate the intent of the cast can give the wrong answer Use relevant C++ casting operator communicates the intent of the cast gives the right answer Use constructor syntax for values int(floatFn()) instead of (int) floatFn() const_cast<T>(expression) const_cast<T> changes the const or volatile qualifier of its argument With T const *p use const_cast<T*>(p) instead of ((T *) p) Declare class members mutable if they need to be updated from a const method Writing through a reference or pointer stripped of its constness may cause undefined behavior! static_cast<T>(expression) Converts to type T, purely based on the types present in expression. Use static_cast<T> when: you intend that the cast does not require any run-time type information Cast enums to a numeric type (int, float, etc.) Cast from void pointer to T pointer Cast across the class hierarchy with multiple inheritance; see http://www.sjbrown.co.uk/2004/05/01/always- use-static_cast/ dynamic_cast<T>(expressio n) Requires RTTI to be enabled Only for pointers or references Returns 0 when object is not a T Resolves multiple inheritance properly reinterpret_cast<T> The most evil of cast operators Subverts the type system completely Should only be needed when dealing with C style APIs that don’t use void pointers Memory Allocation Any call to new or new[] should only appear in a constructor Any call to delete or delete[] should only appear in a destructor Encapsulate memory management in a class More on new and delete new/new[] does’t return 0 when memory is exhausted throws bad_alloc VC6 did it wrong; VS2005/gcc does it right No need to check for zero pointer returned delete/delete[] Deleting a zero pointer is harmless No need to check for zero pointer before calling Always match new[] with delete[] and scalar new with scalar delete Resource Acquisition Memory is just one kind of resource Others: critical section thread lock etc Treat identically to memory: acquire resource in c’tor release resource in d’tor RAII – Resource Acquisition Is Initialization Exceptions Using RAII gives you exception safe code for free Manual management of resources requires try/catch blocks to ensure no memory leaks when an exception is thrown std::auto_ptr<T> Takes ownership of whatever pointer assigned to it ~auto_ptr() calls delete on the pointer release() returns the pointer and releases ownership Calls scalar delete; doesn’t work for arrays Use for temporary buffers that are destroyed when going out of scope or are explicitly assigned to something else on success std::vector<T> Dynamically resizable array Great for fixed-size buffers you need to create for C APIs when the size of the buffer is determined at runtime. Use for temporary arrays of objects If used as an array of pointers, it doesn’t call delete on each pointer boost::shared_ptr<T> Reference counted pointer When reference count reaches zero, delete is called on the underlying pointer Doesn’t guard against cycles Can be good when used carefully, but can be bad when used excessively. It becomes hard to identify the lifetime of resources See boost docs for more boost::ptr_vector<T> Boost container similar to std::vector<T>, but calls delete on each element when it is destroyed See boost docs for more C style strings Don’t use them! Huge source of bugs. Use a string class: Qt’s QString C++ std::string C++ std::basic_string<TCHAR> wxWidgets wxString Pass string classes by const reference Return string classes by value or through reference argument Use std::string::c_str() to talk to C APIs Use of void Don’t use void argument lists: Use void foo() instead of void foo(void) Don’t use void pointers It completely subverts the type system, leading to type errors Callbacks C code can only call back through a function pointer. A void pointer context value is usually passed along to the callback C++ code uses an interface pointer or reference to communicate to its caller. No need to supply a context value as the interface pointer is associated with a class that will hold all the context. Use interfaces instead of function pointers for callbacks #define Use enums to define groups of related integer constants Use static const class members to define integer or floating-point values. Declare them in the .h, define them in the .cpp Use inline functions or methods for small blocks of repeated code Use templates as a way to write type safe macros that expand properly or generate a compiler error Static Polymorphism Static polymorphism exploits similarities at compile time Dynamic polymorphism exploits similarities at runtime Static polymorphism implemented with templates Dynamic polymorphism implemented with virtual methods on classes #if, #else, #endif Used to express static variation in code When compiled one way, you get one variation; when compiled the other way, you get the other variation Better expressed through a template class that expresses the two variations as specifics of arguments to the template Keeps syntactic checking on for both variations all the time
Treat It As An Array. C's Unification of Arrays and Pointers (See Below) Means That True Arrays and These Allocated, Simulated Arrays Are Virtually Interchangeable. Since Arrays Are Always