Some useful tips and factoids for C++ developers.
Get the nth byte of an integer
int
Reserved macro identifiers
Best practice is to avoid using preceding underscores in macro identifiers. 1
Misconceptions about emplace_back() and push_back()
emplace_back() does not move the object that is passed to it. 2
It simply forwards the argument to the constructor of the new object. If it is given an l-value then that is what the constructor for the new object will see and the underlying resource will need to be copied.
The l-value must be explicitly converted to an r-value with std::move() to invoke the correct constructor and avoid a copy.
Since C++11 push_back() has an overload which accepts an r-value and thus it can be be used to avoid the copy just the same as emplace_back()
void
Same name, different compilation unit
Having structs with the same name in separate compilation units can cause undefined behavior. I was getting std::bad_alloc exceptions from code that looked like this:
// Mesh.cpp
;
// Font3D.cpp
;
To the best of my knowledge this shouldn't cause undefined behavior, but regardless I was able to narrow down the problem to being the names of these two structs.
A thread-safe singleton for C++11 or newer
A change made to the standard for C++11 makes possible a very simple thread-safe singleton pattern.
§6.7 [stmt.dcl] p4
If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization.
;
The Minutia of pointers to union members
Pointers to union members are guaranteed to be equivalent
f;
;
;
;
;
From C standard (N1570, 6.7.2.1 Structure and union specifiers):
16 The size of a union is sufficient to contain the largest of its members. The value of at most one of the members can be stored in a union object at any time. A pointer to a union object, suitably converted, points to each of its members (or if a member is a bit- field, then to the unit in which it resides), and vice versa.
Virtual Destructors (when, why, how)
Needed when you want to delete an object with just a pointer to the base class. 3
;
;
// ...
Base* p = new ;
// virtual destructor needs to be defined (even an empty one) or else this causes undefined behavior
delete p;