C++ 标准库是如何实现 std::swap 的?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25286544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:17:45  来源:igfitidea点击:

How does the standard library implement std::swap?

c++templatesswap

提问by Maximilian Mordig

How is the swap function implemented in the STL? Is it as simple as this:

STL中swap函数是如何实现的?是不是就这么简单:

template<typename T> void swap(T& t1, T& t2) {
    T tmp(t1);
    t1=t2;
    t2=tmp;
}

In other posts, they talk about specializing this function for your own class. Why would I need to do this? Why can't I use the std::swapfunction?

在其他帖子中,他们讨论了为您自己的班级专门化此功能。为什么我需要这样做?为什么我不能使用该std::swap功能?

采纳答案by Niall

How is std::swapimplemented?

是如何std::swap实施的?

Yes, the implementation presented in the question is the classic C++03 one.

是的,问题中提出的实现是经典的 C++03 实现。

A more modern (C++11) implementation of std::swaplooks like this:

更现代的 (C++11) 实现std::swap如下所示:

template<typename T> void swap(T& t1, T& t2) {
    T temp = std::move(t1); // or T temp(std::move(t1));
    t1 = std::move(t2);
    t2 = std::move(temp);
}

This is an improvement over the classic C++03 implementation in terms of resource management because it prevents unneeded copies, etc. It, the C++11 std::swap, requires the type Tto be MoveConstructibleand MoveAssignable, thus allowing for the implementation and the improvements.

这是在资源管理方面对经典 C++03 实现的改进,因为它可以防止不需要的副本等。它,C++11 std::swap,要求类型TMoveConstructibleMoveAssignable,从而允许实现和改进.

Why would I need to provide a custom implementation?

为什么我需要提供自定义实现?

A custom implementation of swap, for a specific type, is usually advised when your implementation is more efficient or specific than the standard version.

swap当您的实现比标准版本更有效或更具体时,通常建议针对特定类型使用 的自定义实现。

A classic (pre-C++11) example of this is when your class manages a large amount of resources that would be expensive to copy and then delete. Instead, your custom implementation could simply exchange the handles or pointers required to effect the swap.

一个经典的(C++11 之前的)示例是当您的类管理大量资源时,复制和删除这些资源的成本很高。相反,您的自定义实现可以简单地交换实现交换所需的句柄或指针。

With the advent of std::moveand movable types (and implemented your type as such), circa C++11 and onwards, a lot of the original rationale here is starting to fall away; but nevertheless, if a custom swap would be better than the standard one, implement it.

随着std::move可移动类型的出现(并实现您的类型),大约在 C++11 及以后,这里的许多原始基本原理开始消失;但是,如果自定义交换比标准交换更好,请实施它。

Generic code will generally be able to use your custom swapif it uses the ADLmechanism appropriately.

如果通用代码适当地swap使用ADL机制,它通常能够使用您的自定义。

回答by Useless

How is the swap function implemented in the STL?

STL中swap函数是如何实现的?

Which implementation? It's a specification, not a single concrete library. If you mean how does my compiler's standard library do it, either tell us which compiler that is, or read the code yourself.

哪个实现?这是一个规范,而不是一个具体的库。如果你的意思是我的编译器的标准库如何做到的,要么告诉我们是哪个编译器,要么自己阅读代码。

Is it as simple as this:

是不是就这么简单:

That's essentially the naive version pre-C++11.

这本质上是 C++11 之前的原始版本。

This un-specialized implementation forces a copy: for T = std::vector<SomethingExpensive>in your example, the code translates as:

这种非专业化的实现强制复制:T = std::vector<SomethingExpensive>在您的示例中,代码转换为:

template<typename T> void swap(T& t1, T& t2) {
  T tmp(t1); // duplicate t1, making an expensive copy of each element
  t1=t2;     // discard the original contents of t1,
             // and replace them with an expensive duplicate of t2
  t2=tmp;    // discard the original contents of t2,
             // and replace them with an expensive duplicate of tmp
}            // implicitly destroy the expensive temporary copy of t1

so to exchange two vectors we essentially created three. There were three dynamic allocations and a lot of expensive objects copied, and any of those operations could throw, possibly leaving the arguments in an indeterminate state.

所以为了交换两个向量,我们基本上创建了三个。有三个动态分配和许多昂贵的对象复制,并且这些操作中的任何一个都可能抛出,可能使参数处于不确定状态。

Since this was obviously awful, overloads were provided for expensive containers, and you were encouraged to write overloads for your own expensive types: eg. the std::vectorspecialization had access to the vector's internals, and could swap two vectors without all the copying:

由于这显然很糟糕,因此为昂贵的容器提供了重载,并且鼓励您为自己的昂贵类型编写重载:例如。在std::vector专业化已经进入向量机的内部,并且可以交换两个向量没有所有的复制:

template <typename T> void swap(vector<T> &v1, vector<T> &v2) { v1.swap(v2); }
template <typename T> void vector<T>::swap(vector<T>& other) {
  swap(this->size_, other.size_); // cheap integer swap of allocated count
  swap(this->used_, other.used_); // cheap integer swap of used count
  swap(this->data__, other.data_); // cheap pointer swap of data ptr
}

Note that this involves no copies at all of anything expensive, no dynamic (de)allocation, and is guaranteed not to throw.

请注意,这根本不涉及任何昂贵的副本,没有动态(取消)分配,并且保证不会抛出。

Now, the reason for this specialization is that vector::swap has access to vector's internals, and can safely and efficiently move them around without copying.

现在,这种特殊化的原因是 vector::swap 可以访问 vector 的内部结构,并且可以安全有效地移动它们而无需复制。

Why would I need to do this [specializing ... for your own class] ?

为什么我需要做这件事[专门...为你自己的班级]?

Pre-C++11, for the same reason as std::vector- to make swapping efficient and exception-safe.

Pre-C++11,出于与 - 相同的原因std::vector,使交换高效且异常安全。

Since C++11, you really don't - if you either provide move construction and assignment, or the compiler can generate sane defaults for you.

从 C++11 开始,你真的不需要——如果你提供移动构造和赋值,或者编译器可以为你生成合理的默认值。

The new generic swap:

新的通用交换:

template <typename T> void swap(T& t1, T& t2) {
    T temp = std::move(t1);
    t1 = std::move(t2);
    t2 = std::move(temp);
}

can use move construction/assignment to get essentially the same behaviour as the custom vector implementation above, without needing to write a custom implementation at all.

可以使用移动构造/分配来获得与上面的自定义向量实现基本相同的行为,而根本不需要编写自定义实现。