C++ provides backwards compatability with C, but you will have an easier time if you stay away from certain C-style programming habits. This presentation outlines traps and pitfalls from C style programming in C++ and recommends pure C++ alternatives that lead to fewer surprises, fewer errors and better code. This presentation hasn't been updated for C++11 and is based on C++03.
2. void *pointers
Loses all type information!
Should be avoided when possible
Make the C++ type system work for you,
don’t subvert it
Interfaces to C libraries may require it
3. 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()
4. 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!
5. 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/
7. 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
8. 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
9. 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
10. 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
11. 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
12. 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
13. 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
14. 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
16. 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
17. 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
18. 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
19. #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
20. 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
21. #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