One of the most important concepts introduced in C++11 was move semantics. Move semantics is a way to avoid expensive deep copy operations and replace them with cheaper move operations. Essentially, you can think of it as turning a deep copy into a shallow copy.
Move semantics came along with several more or less related features, such as rvalue references, xvalues, forwarding references, perfect forwarding, and so on. The standard C++ library gained a function template called std::move
, which, despite its name, does not move anything. std::move
merely casts its argument to an rvalue reference to allow moving it, but doesn’t guarantee a move operation. For example, we can write a more effective version of swap
using std::move
:
template<typename T>
void swap(T& a, T& b)
{
T t(std::move (a));
a = std::move (b);
b = std::move (t);
}
This version of swap consists of one move construction and two move assignments and does not involve any deep copies. All is well. However, std::move
must be used judiciously; using it blithely may lead to performance degradation, or simply be redundant, affecting readability of the code. Fortunately, the compiler can sometimes help with finding such wrong uses of std::move
. In this article, I will introduce two new warnings I’ve implemented for GCC 9 that deal with incorrect usage of std::move
.
Continue reading “Understanding when not to std::move in C++”