Index
[]abstractionsalgorithmsallocatorarithmetic operators [See ]arraysassertions [See ]assignmentcopy [See ]assignment operators [See ]asymptotic complexity [See ]at
Summary of Summaries
Organizational and Policy Issues
. Don't sweat the small stuff. (Or: Know what not to standardize.)
Say only what needs saying: Don't enforce personal tastes or obsolete practices.
. Compile cleanly at high warning levels.
Take warnings to heart: Use your compiler's highest warning level. Require clean (warning-free) builds.
Understand all warnings. Eliminate warnings by changing your code, not by reducing the warning level.
. Use an automated build system.
Push the (singular) button: Use a fully automatic ("one-action") build system that builds the whole project without user intervention.
. Use a version control system.
The palest of ink is better than the best memory (Chinese proverb): Use a version control system ( VCS ).
Never keep files checked out for long periods. Check in frequently after your updated unit tests pass.
Ensure that checked-in code does not break the build.
. Invest in code reviews.
Re-view code: More eyes will help make more quality. Show your code, and read others'. You'll all learn and benefit.
STL: Containers
. Use vector by default. Otherwise, choose an appropriate container.
Using the "right container" is great: If you have a good reason to use a specific container type, use that container type knowing that you did the right thing.
So is using vector : Otherwise, write vector and keep going without breaking stride, also knowing you did the right thing.
. Use vector and string instead of arrays.
Why juggle Ming vases? Avoid implementing array abstractions with C-style arrays, pointer arithmetic, and memory management primitives. Using vector or string not only makes your life easier, but also helps you write safer and more scalable software.
. Use vector (and string::c_str) to exchange data with non-C++ APIs.
vector isn't lost in translation: vector and string::c_str are your gateway to communicate with non-C++ APIs. But don't assume iterators are pointers; to get the address of the element referred to by a vector::iterator iter , use &*iter .
. Store only values and smart pointers in containers.
Store objects of value in containers: Containers assume they contain value-like types, including value types (held directly), smart pointers, and iterators.
. Prefer push_back to other ways of expanding a sequence.
push_back all you can: If you don't need to care about the insert position, prefer using push_back to add an element to sequence. Other means can be both vastly slower and less clear.
. Prefer range operations to single-element operations.
Don't use oars when the wind is fair (based on a Latin proverb): When adding elements to sequence containers, prefer to use range operations (e.g., the form of insert that takes a pair of iterators) instead of a series of calls to the single-element form of the operation. Calling the range operation is generally easier to write, easier to read, and more efficient than an explicit loop. (See also.)
. Use the accepted idioms to really shrink capacity and really erase elements.
Use a diet that works: To really shed excess capacity from a container, use the "swap trick." To really erase elements from a container, use the erase-remove idiom.
STL: Algorithms
. Use a checked STL implementation.
Safety first (see ): Use a checked STL implementation, even if it's only available for one of your compiler platforms, and even if it's only used during pre-release testing.
. Prefer algorithm calls to handwritten loops.
Use function objects judiciously: For very simple loops, handwritten loops can be the simplest and most efficient solution. But writing algorithm calls instead of handwritten loops can be more expressive and maintainable, less error-prone, and as efficient.
When calling algorithms, consider writing your own custom function object that encapsulates the logic you need. Avoid cobbling together parameter-binders and simple function objects (e.g., bind2nd , plus ), which usually degrade clarity. Consider trying the [Boost] Lambda library, which automates the task of writing function objects.
. Use the right STL search algorithm.
Search "just enough"the right search may be STL (slower than light), but it'll still be pretty fast: This Item applies to searching for a particular value in a range, or for the location where it would be if it were in the range. To search an unsorted range, use find / find_if or count / count_if . To search a sorted range, use lower_bound , upper_bound , equal_range , or (rarely) binary_search . (Despite its common name, binary_search is usually not the right choice.)
. Use the right STL sort algorithm.
Sort "just enough:" Understand what each of the sorting algorithms does, and use the cheapest algorithm that does what you need.
. Make predicates pure functions.
Predicate purity: A predicate is a function object that returns a yes/no answer, typically as a bool value. A function is pure in the mathematical sense if its result depends only on its arguments (note that this use of "pure" has nothing to do with pure virtual functions).
Don't allow predicates to hold or access state that affects the result of their operator() , including both member and global state. Prefer to make operator() a const member function for predicates (see ).
. Prefer function objects over functions as algorithm and comparer arguments.
Objects plug in better than functions: Prefer passing function objects, not functions, to algorithms. Comparers for associative containers must be function objects. Function objects are adaptable and, counterintuitively, they typically produce faster code than functions.
. Write function objects correctly.
Be cheap, be adaptable: Design function objects to be values that are cheap to copy. Where possible, make them adaptable by inheriting from unary_ - or binary_function .
Type Safety
. Avoid type switching; prefer polymorphism.
Switch off: Avoid switching on the type of an object to customize behavior. Use templates and virtual functions to let types (not their calling code) decide their behavior.
. Rely on types, not on representations.
Don't try to X-ray objects (see ): Don't make assumptions about how objects are exactly represented in memory. Instead, let types decide how their objects are written to and read from memory.
. Avoid using reinterpret_cast.
Lies have short legs (German and Romanian proverb): Don't try to use reinterpret_cast to force the compiler to reinterpret the bits of an object of one type as being the bits of an object of a different type. That's the opposite of maintaining type safety, and reinterpret_cast isn't even guaranteed to do that oranything else in particular.
. Avoid using static_cast on pointers.
Pointers to dynamic objects don't static_cast : Safe alternatives range from using dynamic_cast to refactoring to redesigning.
. Avoid casting away const.
Some fibs are punishable: Casting away const sometimes results in undefined behavior, and it is a staple of poor programming style even when legal.
. Don't use C-style casts.
Age doesn't always imply wisdom: C-style casts have different (and often dangerous) semantics depending on context, all disguised behind a single syntax. Replacing C-style casts with C++-style casts helps guard against unexpected errors.
. Don't memcpy or memcmp non-PODs.
Don't try to X-ray objects (see ): Don't use memcpy and memcmp to copy or compare anything more structured than raw memory.