Explicitly use the type
Most portability problems that generate warnings are caused by our failure to pay attention to types. The standard library and arrays use types size_t
as indexes, and standard container sizes use size_t
types. If size_t is not handled correctly, there may be subtle 64-bit problems lurking that only appear after the initial 32-bit integer index overflow. Another similar problem is the use of char
types and unsigned char
types.
Use the standard library
std::filesystem
C++17 adds new filesystem
libraries that provide portable file system access on all supported compilers.
std::thread
C++11's threading functionality can be based on pthread
or WinThreads
used.
other
Most of the other issues in this series ultimately come down to portability, especially taking care to avoid static types (see the multithreading section below).
Multithreading
Avoid global data
Global data can cause unexpected side effects between functions and can make code difficult or even impossible to parallelize. Even if the code today is not written to be parallelized, there is no reason why it should never be parallelized in the future.
static data
In addition to being global data, static data is not always constructed and destroyed as expected, especially in a cross-platform environment. For example, there is a g++ bug[2] about the destruction order of shared static data loaded from dynamic modules.
shared pointer
std::shared_ptr
Like global variables, allow multiple pieces of code to interact with the same data.
Singleton
Singletons are usually static and/or shared_ptr
implemented.
Avoid heap operations
Heap operations are much slower in a multi-threaded environment, and in many or even most cases copying data will be faster, not to mention move
operations like that.
Mutex and mutable objects are used together (M&M rules, C++11)
For member variables, it's better to use both a mutex and a mutable variable, which works in both directions:
-
Mutable member variables are assumed to be shared variables and therefore should be synchronized (or atomicized) with the mutex lock.
-
If a member variable is itself mutually exclusive, it should be mutable, which is necessary to use it in a const member function.