author:
- luixiao1223
title: 一个不抛出异常的swap函数
来看标准STL版本的swap
namespace std{
template<typename T>
void swap(T& a, T& b)
{
T temp(a);
a = b;
b = temp;
}
}
例子
class WidgetImpl{
public:
private:
int a,b,c;
std::vector<double> v;
};
class Widget{
public:
Widget(const Widget& rhs);
Widget& operator=(const Widget& rhs)
{
*pImpl = *(rhs.pImpl);
}
private:
WidgetImpl* pImpl;
};
如果你对 Widget调用swap那么实际上
pImpl是被复制的。这是十分缺乏效率的。有没有办法提高效率?
提高效率
无法通过编译
namesapce std{
template<>
void swap<Widget> (Widget& a,
Widget& b)
{
swap(a.pImpl, b.pImpl)
}
}
template<>表示是一个全特化。
无法同构编译,因为a,b企图访问private
我们可以在Widget中声明一个swap public函数
class Widget{
public:
void swap(Widget& other)
{
using std::swap;
swap(this->pImpl, other.pImpl); // 错误
}
};
namesapce std{
template<>
void swap<Widget> (Widget& a,
Widget& b)
{
a.swap(b);
}
}
我们这样就解决了swap问题的效率问题了。
如果 Widget and WidgetImpl都是template class怎么办
template<typename T>
class WidgetImpl{...};
template<typename T>
class Widget{...};
错误代码
namesapce std{
template<typename T>
void swap<Widget<T>>(Widget<T>& a,
Widget<T>& b) // 错误的。
{
a.swap(b);
}
}
原因: C++只允许class template的偏特化。不支持函数
templates上的偏特化。
Still Error
下面的代码是重载,不是偏特化,也不是全特化。
namespace std{
template<typename T>
void swap(Widget<T>& a,
Widget<T>& b)
{
a.swap(b);
}
}
- 错误的地方时,C++不允许向std里面添加templates。即包括classes,functions.
- std允许客户全特化std内的templates。偏特化可以么?
Correct
namespace WidgetStuff{
template<typename T>
class Widget{...};
template<typename T>
void swap(Widget<T>& a,
Widget<T>& b)
{
a.swap(b);
}
};
把这个重构函数放到另外的命名空间中。
using
template<typename T>
void soSomething(T& obj1, T& obj2)
{
using std::swap;
swap(obj1, obj2);
}
使用using是让STL的swap暴露出来。编译器会去当前命名空间找更为特殊的swap版本。如果没找到去global
space中找。然后再用这个std的swap版本。
成员版的swap绝对不要抛出异常
内置类型的操作基本不会抛出异常。