Yac*_*oby 25
对于大多数类,默认交换很好,但是,默认交换在所有情况下都不是最佳的.最常见的例子是使用Pointer to Implementation惯用语的类.与默认交换一样,大量内存会被复制,如果是专门的交换,只需交换指针就可以显着加快速度.
如果可能,它不应该是类的朋友,但是它可能需要访问您可能不希望在类API中公开的私有数据(例如,原始指针).
Mar*_*ork 23
标准版本的std :: swap()适用于大多数可分配的类型.
void std::swap(T& lhs,T& rhs)
{
T tmp(lhs);
lhs = rhs;
rhs = tmp;
}
Run Code Online (Sandbox Code Playgroud)
但它不是一个最佳实现,因为它调用复制构造函数,然后调用赋值运算符.
通过为您的类添加您自己的std :: swap()版本,您可以实现swap()的优化版本.
例如std :: vector.上面定义的默认实现非常昂贵,因为您需要复制整个数据区域.可能会释放旧数据区域或重新分配数据区域,并在复制的每个项目上调用包含类型的复制构造函数.一个专门的版本有一个非常简单的方法来做std :: swap()
// NOTE this is not real code.
// It is just an example to show how much more effecient swaping a vector could
// be. And how using a temporary for the vector object is not required.
std::swap(std::vector<T>& lhs,std::vector<T>& rhs)
{
std::swap(lhs.data,rhs.data); // swap a pointer to the data area
std::swap(lhs.size,rhs.size); // swap a couple of integers with size info.
std::swap(lhs.resv,rhs.resv);
}
Run Code Online (Sandbox Code Playgroud)
因此,如果您的类可以优化swap()操作,那么您应该这样做.否则将使用默认版本.
我个人喜欢将swap()实现为非投掷成员方法.然后提供std :: swap()的专用版本:
class X
{
public:
// As a side Note:
// This is also useful for any non trivial class
// Allows the implementation of the assignment operator
// using the copy swap idiom.
void swap(X& rhs) throw (); // No throw exception guarantee
};
// Should be in the same namespace as X.
// This will allows ADL to find the correct swap when used by objects/functions in
// other namespaces.
void swap(X& lhs,X& rhs)
{
lhs.swap(rhs);
}
Run Code Online (Sandbox Code Playgroud)
sth*_*sth 17
如果你想交换(例如)两个向量而不了解它们的实现,你基本上必须做这样的事情:
typedef std::vector<int> vec;
void myswap(vec &a, vec &b) {
vec tmp = a;
a = b;
b = tmp;
}
Run Code Online (Sandbox Code Playgroud)
如果a并且b包含许多元素,这是无效的,因为所有这些元素都被复制a,b和tmp.
但是,如果交换函数知道并且可以访问向量的内部,则可能有更高效的实现:
void std::swap(vec &a, vec &b) {
// assuming the elements of the vector are actually stored in some memory area
// pointed to by vec::data
void *tmp = a.data;
a.data = b.data;
b.data = tmp;
// ...
}
Run Code Online (Sandbox Code Playgroud)
在这个实现中,只需要复制几个指针,而不是像第一个版本中那样复制所有元素.由于此实现需要访问向量的内部,因此它必须是友元函数.
Pie*_*ter 10
我把你的问题解释为基本上三个不同(相关)的问题.
swap)?为什么STL需要交换?
STL友好类需要的原因swap是swap在许多STL算法中用作原始操作.(例如reverse,sort,partition等使用典型地实施swap)
为什么要实现专门的交换(iso依赖于默认值
swap)?
你的问题的这部分已经有很多(好的)答案.基本上,了解类的内部经常允许您编写更加优化的swap函数.
为什么要把它作为朋友实施?
STL算法将始终将swap作为自由函数调用.所以它需要作为非成员函数可用才有用.
并且,因为当你可以使用内部结构的知识来编写更有效的交换时,编写自定义交换是唯一有益的,这意味着你的自由函数将需要访问你的类的内部,因此是朋友.
基本上,它不具备成为朋友,但如果它不需要成为朋友,通常有没有理由要么实现自定义交换.
请注意,您应确保自由函数与您的类位于同一名称空间内,以便STL算法可以通过Koening查找找到您的自由函数.
| 归档时间: |
|
| 查看次数: |
11753 次 |
| 最近记录: |