为什么每个STL容器都有一个定义为成员函数的交换函数?

考虑STL中的queue容器。

据我的理解, <algorithm>头文件中提供的swap()可以正常工作。

我知道swap()只会表面复制queue实例,也就是说,只有frontrear指针会随着size和其他数据成员一起被复制。

两个队列中的条目不会在物理上交换位置,但我不明白为什么在任何情况下都需要这样做,因为一旦交换了指针和大小,两个队列就会有效地交换。


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

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

请注意,这个通用std::swap不知道传入的内部对象的内容(例如,可以使用任意用户类型调用它),因此必须进行复制。 请注意,对于容器,这意味着复制元素。

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

由于引入了移动语义,所以通用交换可以使用移动更高效。 在概念上,再一次:

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

当然,在实践中,它可能对涉及非投掷的移动操作以及各种额外的比特有要求。

随着移动语义的到位,优化的成员版本可能不像以前那么重要。 但是在知道某个类型的确切实现细节后,仍然有可能通过交换它可以比三种通用移动更快。


除了上面的讨论外,请注意标准库中定义的几乎所有类型都存在std::swap类型特定的重载。 这些重载所做的只是在其中一个操作数上调用优化的swap成员函数。 这样,你就拥有了两全其美的优势:一个通用的免费函数swap ,可以用任何东西调用,但是它为标准库知道的所有东西都优化了实现。

可以放弃成员函数并直接在std::swap重载内提供优化实现,但这意味着他们可能需要成为朋友,并且可能被认为对用户代码更糟糕。


由于免费的std::swap对每个容器都有重载,所以成员函数swap并不是真的必要。 免费的重载可以被声明为friend并执行所有特定于实现的特定于容器的魔术来实现高效的交换。

实际上,它们调用成员swap s。 我想这可以提高如何调用这些函数的灵活性,并且可以节省大量的friend声明。

我不知道还有比这更多的东西。


当统一调用语法提议(Bjarne Stroustrup 2014版)最终被采用时,经过一些最终调整后,您的问题将变得毫无意义,因为std::swap(my_queue, another_queue)my_queue.swap(other_queue)很可能会完全相同功能的别名。 不幸的是,C ++ 17不会发生这种情况。 也许在C ++ 20中? 人们可以梦想...

链接地址: http://www.djcxy.com/p/95615.html

上一篇: Why does every STL container have a swap function defined as a member function?

下一篇: Docker Nginx stopped: [emerg] 1#1: host not found in upstream