更新时间:2023-11-11 18:00:40
这是Terry的回答。
This is in addition to Terry's answer.
我们必须在0x之前在C ++中使 swap
函数的原因是因为一般的***函数 std :: swap
效率较低(而且通用性较低)。它做了一个参数的副本,然后有两个重新分配,然后释放基本上浪费的副本。制作一个重量级的副本是浪费时间,当我们作为程序员知道我们真正需要做的是交换内部指针和whatnot。
The reason we had to make swap
functions in C++ prior to 0x is because the general free-function std::swap
was less efficient (and less versatile) than it could be. It made a copy of a parameter, then had two re-assignments, then released the essentially wasted copy. Making a copy of a heavy-weight class is a waste of time, when we as programmers know all we really need to do is swap the internal pointers and whatnot.
但是,右值引用完全解除这一点。在C ++ 0x中, swap
实现为:
However, rvalue-references relieve this completely. In C++0x, swap
is implemented as:
template <typename T>
void swap(T& x, T& y)
{
T temp(std::move(x));
x = std::move(y);
y = std::move(temp);
}
这更有意义。而不是复制数据,我们只是移动数据。这甚至允许不可复制的类型,如流,被交换。 C ++ 0x标准的草案规定,为了使用 std :: swap
交换类型,它们必须是可值构造的,并且右值可分配(显然)。
This makes much more sense. Instead of copying data around, we are merely moving data around. This even allows non-copyable types, like streams, to be swapped. The draft of the C++0x standard states that in order for types to be swapped with std::swap
, they must be rvalue constructable, and rvalue assignable (obviously).
此版本的 swap
本质上会执行任何自定义书写的交换函数。考虑一个类,我们通常写 swap
(例如这个哑向量):
This version of swap
will essentially do what any custom written swap function would do. Consider a class we'd normally write swap
for (such as this "dumb" vector):
struct dumb_vector
{
int* pi; // lots of allocated ints
// constructors, copy-constructors, move-constructors
// copy-assignment, move-assignment
};
以前, swap
的所有数据,之后再丢弃它。我们的自定义 swap
函数只是交换指针,但在某些情况下可能会笨拙使用。在C ++ 0x中,move实现了相同的最终结果。调用 std :: swap
将生成:
Previously, swap
would make a redundant copy of all our data, before discarding it later. Our custom swap
function would just swap the pointer, but can be clumsy to use in some cases. In C++0x, moving achieves the same end result. Calling std::swap
would generate:
dumb_vector temp(std::move(x));
x = std::move(y);
y = std::move(temp);
这可以翻译成:
dumb_vector temp;
temp.pi = x.pi; x.pi = 0; // temp(std::move(x));
x.pi = y.pi; y.pi = 0; // x = std::move(y);
y.pi = temp.pi; temp.pi = 0; // y = std::move(temp);
编译器当然会删除多余的赋值语句:
The compiler will of course get rid of redundant assignment's, leaving:
int* temp = x.pi;
x.pi = y.pi;
y.pi = temp;
这是完全我们的自定义 swap
首先会做。所以在C ++ 0x之前,我同意你的建议,自定义 swap
不再需要了,引入rvalue-references。 std :: swap
将在任何实现move函数的类中正常工作。
Which is exactly what our custom swap
would have made in the first place. So while prior to C++0x I would agree with your suggestion, custom swap
's aren't really necessary anymore, with the introduction of rvalue-references. std::swap
will work perfectly in any class that implements move functions.
事实上,实现 swap
函数应该成为坏习惯。任何需要 swap
函数的类也需要rvalue函数。但是在这种情况下,根本不需要自定义 swap
的混乱。代码大小增加了(两个ravlue函数对一个 swap
),但是右值引用不仅仅适用于交换,留给我们积极的权衡。 (总体来说代码更快,界面更干净,代码更多,没有更多 swap
ADL麻烦。)
In fact, I'd argue implementing a swap
function should become bad practice. Any class that would need a swap
function would also need rvalue functions. But in that case, there is simply no need for the clutter of a custom swap
. Code size does increase (two ravlue functions versus one swap
), but rvalue-references don't just apply for swapping, leaving us with a positive trade off. (Overall faster code, cleaner interface, slightly more code, no more swap
ADL hassle.)
或者不是我们可以默认
右值函数,我不知道。我会稍后查找它,或者也许有人可以在里面,但这肯定是有帮助的。 :)
As for whether or not we can default
rvalue functions, I don't know. I'll look it up later or maybe someone else can chime in, but that would sure be helpful. :)
即使如此,允许默认
rvalue函数代替
。因此,实质上,只要它们允许 = default
右值函数,您的请求已经完成。 :)
Even so, it makes sense to allow default
rvalue functions instead of swap
. So in essence, as long as they allow = default
rvalue functions, your request has already been made. :)
编辑:我做了一些搜索,提议 = default
move是proposal n2583
。根据这(我不知道如何读得很好),它是回迁。它在标题为未准备好C ++ 0x,但打开以后将重新提交的部分列出。所以看起来像它不会是C ++ 0x的一部分,但可能稍后添加。
I did a bit of searching, and the proposal for = default
move was proposal n2583
. According to this (which I don't know how to read very well), it was "moved back." It is listed under the section titled "Not ready for C++0x, but open to resubmit in future ". So looks like it won't be part of C++0x, but may be added later.
有点失望。 :(
编辑2:再看一下,我发现这个:定义移动特殊成员函数这是更新的,看起来像我们可以默认 move
。Yay!
EDIT 2: Looking around a bit more, I found this: Defining Move Special Member Functions which is much more recent, and does look like we can default move
. Yay!