devxlogo

Move Semantics: Make Your Next Move

Move Semantics: Make Your Next Move

opy construction, assignment, container reallocation, string concatenation, and string copying are all instances of copy operations. However, in recent years a new paradigm is emerging: move semantics. This discussion presents the concept of moving?by showing how it differs from traditional copying?as well as move semantics applications and their benefits.


Though there are many tasks in which copying is the correct operation to carry out, frequently there are other instances in which the reduplication of resources that copying requires is unnecessary.


Apply move semantics through moved-based swapping to optimize swap operations, string concatenation, container reallocation, and many other common operations.

Moving versus Copying
Moving, as opposed to copying, means that a target object pilfers (get used to this technical term!) the source object’s resources, instead of reduplicating or sharing them. By contrast, copying means that the target and the source objects end up having two identical, though independent, copies of the resource. Here’s a trivial example of copying:

const char msg[]="hi";char s[3]strcpy(s, msg);

After the execution of the strcpy() call, you have two strings: msg and s, that contain the same values in two different memory locations. The copy operation didn’t modify the source.

Move-Based Swapping
In many cases, copying is the right operation to do; you really want to copy the state of the source object to the target object without altering the source. However, there are programming tasks that can be implemented without such reduplication of resources. Take, for example, the concept of swapping, that is, the target and the source exchange their states. A naive swap implementation would create redundant copies:

template  void swap(T t1, T t2){ T temp=t1; //copy t1=t2; //copy t2=temp; //copy}

When the swap() arguments are integers or Boolean values, this trivial implementation is efficient. However, suppose you want to swap two strings:

string s1="hello";string s2="world";

Swapping s1 and s2 by means of creating a temporary string object, copying one of the strings to it, and then copying two more strings is unnecessarily slow:

void swapstrings(string s1, string s2){ string temp=s1; //copy s1=s2; //copy s2=temp; //copy}

Instead of messing with memory allocations and linear copying of characters, there’s a simpler and more efficient technique: moving the two strings. In this context, moving means exchanging the internal pointers and sizes of the string objects, as you can see in this pseudo-code:

void swapstr(string &a, string &b){ size_t tempsz=a.size(); const char *p= a.data();//a pilfers b's resources  a.size=b.size();   a.data=b.data();//pointer assignment,not buffer copying//b pilfers a's resources b.size=tempsz;  b.data=p;}

This version costs six simple assignments of word-sized datatypes. By contrast, a copy-based swap is a linear operation, and its execution time depends on the length of the two strings. The longer their cumulative length is, the slower the operation is.Container Swapping
If the swapping of two strings can be optimized dramatically by using move semantics, imagine the effect of swapping two containers in this manner. Recall that containers also use swap() implicitly, when they reallocate storage for new elements, for instance.

A copy-based container reallocation consists of these steps:

  1. Allocate a raw memory buffer that is large enough to accommodate the container’s existing elements and the new ones.
  2. Copy-construct each element onto the new raw buffer.
  3. Destroy the original elements.
  4. Release the original memory buffer.

Unquestionably, this reallocation scheme is very expensive and slow.

The performance overhead of reallocation can be reduced drastically if the container moves its elements instead of copy-constructing them. Think of a vector of strings, for example. Instead of reallocating every string object using a copy-based swap, the vector can call move-based swap() to move strings from the original memory buffer to the new memory buffer. In other words, the newly constructed strings will simply swap their null buffer addresses and zero sizes with the original strings. Neither memory reallocation of string buffers nor character copying are required in this case.

Things get even better when you swap two containers. Theoretically, this operation would require member-wise copying of elements to a temporary container and a subsequent copying of each container’s elements. You guessed it: a move operation can swap the contents of two containers by simply exchanging their data pointers and sizes. The performance improvement in this case is fantastic.The Move Movement and You
The good news is that state-of-the-art STL implementations already use move semantics to optimize swap operations, string concatenation, container reallocation, and many other common operations. Your responsibility as a programmer is to use the specialized swap() member function of every standard container when possible. Generally speaking:

t.swap(t2)

is more efficient than the generic form:

std::swap(t1, t2) 

When designing a new class, consider implementing a swap() member function that uses move semantics. Such a member function is particularly useful if the class in question owns resources that are slow or expensive to copy, such as database connections, GUI elements, and so on.

Start Moving
It’s impossible to sign a C++ article these days without a reference to the C++09 standard. C++09 will include a new type of references called rvalue references. Rvalue references are similar to the references you’ve known for many years, except that they can bind to non-const rvalues?for example, temporaries. One of the main purposes of adding rvalue references to C++ is streamlining the implementation of move semantics and perfect forwarding. As you’ve seen, move semantics can be implemented even without rvalue references. However, once rvalue references are incorporated into mainstream C++, moving will become widespread. Expect to hear more about move-constructors (in addition to?or instead of?traditional copy-constructors), auto_ptr-style smart pointers, and, overall, an even faster and better C++!

devxblackblue

About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist