考虑写出一个不抛出异常的高效的swap函数
首先得说明为什么我们要优化我们的swap函数,swap函数是异常安全性编程的脊柱,同时也是处理operator=自我赋值的重要手段。要编写一个优化版本的swap函数,我们首先需要了解标准库是怎们定义的swap函数:
namespace std
{
template <typename T>
swap(T&lhs,T&rhs)
{
T temp(lhs);
lhs=rhs;
rhs=temp;
}
}
这个函数很直观,但是在某些情况写是可以优化的,考虑一下这种pimpl手法(pointer to implementation) 该swap的效率显然可以进一步提升:
class WidgetImpl
{
public:
...
private:
int a,b,c,d;
vector<double> v;
}
现在我们存在这么两个类,现在我们如果需要交换两个对象,显然我们调用std::swap()函数,但是很明显std::swap函数的效率需要拷贝多次,效率极低。正确的做法是只交换两个指针的指向。那么正确的做法如下:
class Widget
{
public:
Widget(const Widget&);
Widget& operator=(const Widget&){ ...;*pImpl=*(rhs.pImpl);...}
void swap(Widget& rhs){
using std::swap; swap(pImpl,rhs.pImpl);
}
private:
WidgetImpl *pImpl;
}
同时我们需要特化我们自己的swap函数:
namespace std
{
template <>
swap<Widget>(T&lhs,T&rhs)
{
lhs.swap(rhs);
}
}
这种做法是合理的,但是如果我们的类是一个模板类,但是c++并不允许对函数得偏特化,所以我们在类的命名空间中重载swap函数就行。
namespace WidgetStuff
{
template<typename T>
class Widget{...};
template<typename T>
void swap(Widget<T> &lhs,Widget<T> &rhs)
{
lhs.swap(rhs);
}
}
这样我们在使用的时候,引入std::swap 自动根据类型进行了推断
template <typename T>
void doSomthing(T& lhs,T&rhs)
{
using std::swap;
swap(lhs,rhs);
}