Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my swap<string,string> far slower than the std version?

This is my C++ code:

inline static void swap(std::string& a1, std::string& a2) {    
    std::string temp( std::move(a1));
    a1 = std::move( a2 );
    a2 = std::move( temp );
}

I ran this function 1000000 times and it took 78ms on average, but the std one just took 13ms. I just looked at the implementation of std::swap, I found it just the the same as mine, so why is mine so slow?

like image 272
user3126461 Avatar asked Feb 06 '17 20:02

user3126461


People also ask

Does STD swap copy or move?

std::swap(a,b) is required to exchange the states. That amounts to moving the state of b to a and the state of a to b . So the logical 'burden' for move is greater than swap. It's not uncommon for std::move to in effect perform a swap.

What does std :: swap do?

The function std::swap() is a built-in function in the C++ Standard Template Library (STL) which swaps the value of two variables. Parameters: The function accepts two mandatory parameters a and b which are to be swapped. The parameters can be of any data type.

Does STD swap use move semantics?

Using std::move wherever we can, as shown in the swap function above, gives us the following important benefits: For those types that implement move semantics, many standard algorithms and operations will use move semantics and thus experience a potentially significant performance gain.


1 Answers

According to the standard §21.3.2.8/p1 swap [string.special] (Emphasis Mine):

template<class charT, class traits, class Allocator>
void swap(basic_string<charT, traits, Allocator>& lhs,
basic_string<charT, traits, Allocator>& rhs)
noexcept(noexcept(lhs.swap(rhs)));

1 Effects: Equivalent to: lhs.swap(rhs);

Consequently, std::swap specializes/has an overload for std::string and is equivalent as calling the member function std::basic_string::swap.

A possible implementation would be:

template<class Elem, class Traits, class Alloc> 
inline
void
swap(std::basic_string<Elem, Traits, Alloc>& left, 
     std::basic_string<Elem, Traits, Alloc>& right) noexcept(noexcept(left.swap(right))) {
  left.swap(right);
}

As for why your implementation is slower, my guess is that even if you move the one string to the another, the destructor for the temporary string will still be called. Something that is not the case in the STL compatible implementation above.

like image 162
101010 Avatar answered Nov 15 '22 06:11

101010