AI写作智能体 自主规划任务,支持联网查询和网页读取,多模态高效创作各类分析报告、商业计划、营销方案、教学内容等。 广告
## 条款25:考虑写出一个不抛异常的 swap 函数 Consider support for a non-throwing swap. ### class template 偏特化 所谓置换两个对象值,就是将两个对象的值赋予彼此,在缺省情况下,swap 动作可由标准库提供的算法完成: ```cpp namespace std { template<typename T> void swap(T& a, T& b) { T temp(a); a = b; b = temp; } } ``` 只要 T 类型支持 copying(通过 copy 构造函数和 copy assignment 操作符完成),就可以使用标准库提供的 swap 算法。但是对某些类型而言,复制操作的代价很大,例如“以指针指向一个对象,内含真正数据”的类型: ```cpp class WidgetImpl { private: int a, b, c; std::vector<double> v; // 可能要复制很长时间; }; class Widget { public: Widget(const Widget& rhs) { ... *pImpl = *(rhs.pImpl); } ... private: WidgetImpl* pImpl; }; ``` 对于这种类型的置换操作,只需要置换 `pImpl` 的值即可,无需将整个对象拷贝。而实践这一思路的唯一做法是:将 std::swap 针对 Widget 特化: ```cpp class Widget { public: ... void swap(Widget& other) { std::swap(pImpl, other.pImpl); // 这里使用标准库的 swap; } }; namespace std { template<> void swap<Widget>(Widget& a, Widget& b) { a.swap(b); } } ``` ### function template 偏特化 假设 Widget 和 WidgetImpl 都是 class template,这时以下的写法会企图偏特化一个 function template,但 C++ 只允许对 class template 偏特化: ```cpp namespace std { template<typename T> void swap< Widget<T> >(Widget<T>& a, Widget<T>& b); } ``` 所以想要偏特化一个 function template 的惯用做法是添加一个重载版: ```cpp namespace WidgetStuff { template<T> void swap(Widget<T>& a, Widget<T>& b) { a.swap(b); } } ``` 一般而言,重载 function template 时要注意命名空间,std 的内容完全由 C++ 标准委员会决定,它禁止我们膨胀哪些已经声明好的东西。