为什么每个 STL 容器都有一个定义为成员函数的交换函数? [英] Why does every STL container have a swap function defined as a member function?

查看:26
本文介绍了为什么每个 STL 容器都有一个定义为成员函数的交换函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑 STL 中的 queue 容器.

Consider the queue container in STL.

据我了解, 标头中的 swap() 可以正常工作.

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

我理解swap()只会从表面复制queue实例,即只有frontrear 指针将与 size 和其他数据成员一起被复制.

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.

推荐答案

在 C++11 引入移动语义之前,std::swap 的通用实现别无选择,只能做两个副本.从概念上讲,这是:

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;
}

请注意,这个通用的 std::swap 对传入的对象的内部结构一无所知任何(因为它可以用任意用户类型调用,例如例如),因此必须进行复制.请注意,对于容器,这意味着复制元素.

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.

提供一个优化的成员函数swap,它只是重新指向一些内部指针,因此是一个巨大的性能优势.

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.

除了上面的讨论之外,请注意std::swap 的特定于类型的重载几乎适用于标准库中定义的所有类型.这些重载所做的只是在操作数之一上调用优化的 swap 成员函数.这样,您就拥有了两全其美的优势:一个通用的自由函数 swap 可以用任何东西调用,但它已经针对标准库所知道的一切优化了实现.

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.

可以放弃成员函数并直接在 std::swap 重载中提供优化的实现,但这意味着它们可能需要成为友元并被视为用户代码的可访问性较差.

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.

这篇关于为什么每个 STL 容器都有一个定义为成员函数的交换函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆