Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does every STL container have a swap function defined as a member function?

Tags:

c++

stl

Consider the queue container in STL.

It is my understanding that swap() available in the <algorithm> header would work just fine.

I understand that swap() will only copy the queue instances superficially, that is, only the front and rear pointers will be copied, along with the size, and other data members.

The entries in the two queues would not physically swap places, but I do not see why that would be nescessary in any scenario as once the pointers and size is swapped, the two queues will effectively be swapped.

like image 779
Aayush Mahajan Avatar asked Mar 10 '17 12:03

Aayush Mahajan


People also ask

Is swap part of STL?

The function std::swap() is a built-in function in the C++ Standard Template Library (STL) which swaps the value of two variables.

What do all STL containers define?

An STL container is a collection of objects of the same type (the elements). Container owns the elements. Creation and destruction is controlled by the container.

What is the return type of the STL swap () function?

std::swap() Return Type: void - It returns nothing.

What is the function of swap in C ++?

The swap() function is defined in the header <vector> . It swaps the contents of two vectors with each other. The sizes of the two vectors may be different.


2 Answers

Since the free std::swap has overloads for each container, you're right that member function swaps aren't really necessary. The free overloads could have been declared friends and performed all the implementation-specific, container-specific magic to make an efficient swap.

As it is, they invoke the member swaps. I suppose this allows for additional flexibility in how to call those functions, and it saves lots of friend declaration.

I'm not aware that there's anything more to it than that.

like image 78
Lightness Races in Orbit Avatar answered Nov 05 '22 04:11

Lightness Races in Orbit


Before C++11 introduced move semantics, the generic implementation of std::swap had no choice but to do two copies. Conceptually, this:

template <class T>
void swap(T &a, T &b)
{
  T t(a);
  a = b;
  b = t;
}

Notice that this generic std::swap doesn't know anything about internals of the object passed in (because it can be called with an arbitrary user type, for example), and thus has to do copies. Note that for containers, this means copying the elements.

Providing an optimised member function swap which just re-points some internal pointers is therefore a huge performance win.

Since move semantics were introduced, the generic swap can be made more efficient using moves. Again, conceptually:

template <class T>
void swap(T &a, T &b)
{
  T t(::std::move(a));
  a = ::std::move(b);
  b = ::std::move(t);
}

Of course, in practice, it probably has requirements about the move operations involved being non-throwing, and all sorts of extra bits.

With move semantics in place, the optimised member versions are perhaps less important than they were before. But it's still possible that with knowledge of the exact implementation details of a type, swapping it can be faster than three generic moves.


In addition to the discussion above, notice that type-specific overloads of std::swap exist for almost all types defined in the standard library. What these overloads do is simply call the optimised swap member function on one of the operands. That way, you have the best of both worlds: a generic free function swap which can be called with anything, but which has optimised implementations for everything the standard library is aware of.

It would be possible to forego the member functions and provide the optimised implementations inside the std::swap overloads directly, but this would mean they'd likely need to be friended and could be perceived as worse accessible to user code.

like image 40
Angew is no longer proud of SO Avatar answered Nov 05 '22 04:11

Angew is no longer proud of SO