Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is specializing std::swap deprecated now that we have move semantics? [duplicate]

Possible Duplicate:
Move semantics == custom swap function obsolete?

This is how std::swap looks like in C++11:

template<typename T> void swap(T& x, T& y) {   T z = std::move(x);     x = std::move(y);     y = std::move(z); } 

Do I still have to specialize std::swap for my own types, or will std::swap be as efficient as it gets, provided that my class defines a move constructor and a move assignment operator, of course?

like image 703
fredoverflow Avatar asked Dec 23 '11 14:12

fredoverflow


People also ask

Does std :: move make a copy?

std::move is actually just a request to move and if the type of the object has not a move constructor/assign-operator defined or generated the move operation will fall back to a copy.

What happens when you to std :: move?

std::move itself does "nothing" - it has zero side effects. It just signals to the compiler that the programmer doesn't care what happens to that object any more. i.e. it gives permission to other parts of the software to move from the object, but it doesn't require that it be moved.

What does std :: move () do?

std::move. std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object. In particular, std::move produces an xvalue expression that identifies its argument t . It is exactly equivalent to a static_cast to an rvalue reference type.

How do you swap classes in C++?

Create a class Swap, declare three variables in it, i.e., a, b, and temp and create a constructor for inputs. Declare a friend function in it. Define the friend function outside the class scope by taking arguments as call by reference to pass the copy of Swap Object. Perform the swap operation with Swap variables.


2 Answers

The specialization of std::swap is now optional, but not deprecated. The rationale is performance.

For prototyping code, and perhaps even for much shipping code, std::swap will be plenty fast. However if you're in a situation where you need to eek out every little bit from your code, writing a custom swap can still be a significant performance advantage.

Consider the case where your class essentially has one owning pointer and your move constructor and move assignment just have to deal with that one pointer. Count machine loads and stores for each member:

Move constructor: 1 load and 2 stores.

Move assignment: 2 loads and 2 stores.

Custom swap: 2 loads and 2 stores.

std::swap is 1 move construction and 2 move assignments, or: 5 loads and 6 stores.

A custom swap is potentially still two or three times faster than std::swap. Though any time you're trying to figure out the speed of something by counting loads and stores, both are going to be wicked fast.

Note: In computing the cost of your move assignment, be sure and take into account that you will be moving into a moved-from value (in the std::swap algorithm). This often negates the cost of a deallocation, though at the cost of a branch.

like image 184
Howard Hinnant Avatar answered Sep 28 '22 00:09

Howard Hinnant


Is specializing std::swap deprecated now that we have move semantics?

No. This is the generic version, but you can optimize it to skip a third move operation. My preference is to combine copy-and-swap idiom with customizing std::swap for my classes.

That means I will have:

class Aaaa { public:     Aaaa(); // not interesting; defined elsewhere     Aaaa(Aaaa&& rvalueRef); // same     Aaaa(const Aaaa& ref); // same     ~Aaaa(); // same     Aaaa& operator=(Aaaa object) // copy&swap     {         swap(object);         return *this;     }     void swap(Aaaa& other)     {         std::swap(dataMember1, other.dataMember1);         std::swap(dataMember2, other.dataMember2);         // ...     }      // ... };  namespace std {     template<> inline void std::swap(Aaaa& left, Aaaa& right)     { left.swap(right); } } 
like image 21
utnapistim Avatar answered Sep 28 '22 00:09

utnapistim