您的位置:首页 > Web前端

Effective STL 读书笔记 8

2006-03-29 02:31 309 查看
Item 38:为满足按值传递设计函数类(functor class)。

我们习惯上:将 functor 称作函数对象,而不是仿函数;将 functor class 称作函数类,而不是其他。

一些 STL 的实现中的一些算法并不允许将函数对象(算法中的谓词)按引用传递,而且这样的编程风格也并不常见。所以,算法中的函数对象会按值传递,即在算法中被复制。

copy 导致两个问题:

copy 导致效率问题,为了高效,functor 必须尽可能的小。

functor 不能是多态的,即不能有继承,因为在 copy 过程中会被裁切。

解决方法,将接口和实现分离,利用Bridge:

template<typename T>
class MyFunctor : public unary_function<T, void> { // See item 40
public:
void operator() (const T& val) const {
m_pImpl->operator()(val);
}
private:
MyFunctorImpl<T> *m_pImpl;
};

template<typename T>
class MyFunctorImpl {
public
virtual void operator() (const T& val) const;
private:
//some member.
};

上面的实现如有必要使用 smart_ptr。

以上这种做法在 Effective C++ Item 34 中有提到,在 Design Pattern 中称作 Bridge 模式,在 Exceptional C++ 中被称作 Pimpl Idiom。

Item 39:使谓词成为纯函数。

谓词,predicate,是一个返回值为 bool 类型(或者可以转变成 bool 类型)的函数,在 STL 中随处可见,如:关联容器的比较函数,find_if 的比较函数等。

纯函数,pure function,是一个函数其返回值仅与其输入参数有关(与环境状态,如时间,无关),而且输入参数不被改变。

只需记住的“谓词必须是纯函数!”。

Item 40:使函数类可适配。

STL 中有四个函数适配器:not1, not2, bind1st, bind2nd。Boost 有更多。

适配器函数需要一些 typedef 才能够工作,定义合适的 typedef 的函数类被称为可适配的。

普通函数(或者说函数指针)没有相应的 typedef 所以不能够被上面四个函数适配器所用,必须使用 ptr_fun 等封装,而 ptr_fun 所做的工作就是 typedef。

所以你必须总是使你定义的函数类成为可适配的。

方法,继承自:unary_function 或 binary_function。

Item 41:理解 ptr_fun,mem_fun,及 mem_fun_ref。

ptr_fun 是为了让普通函数可用于函数适配器而加入的,见 Item 40。

mem_fun 与 mem_fun_ref 是为了使 STL 算法可以将成员函数(member functions )当作参数,而加入的,如下:

list<Widget *> lpw;
for_each(lpw.begin(), lpw.end(),
mem_fun(&Widget::test)); // pw->test();

vector<Widget> vw;
for_each(vw.begin(), vw.end(),
mem_fun_ref(&Widget::test)); // w.test();

Item 42:确定 less<T> 与 operator< 同意。

关联容器默认使用 less<T> 作为比较操作,默认的 less<T> 调用对象的 operator< 操作。所以,不要随便的对 less<T> 进行模板特化(对于某些编译器来说在 std 命名空间里特化是不允许的),如果需要特化,保证 less<T> 与 operator< 同意,否则会造成混淆。

如果要自定义容器的排序算法,重新编写排序函数(函数对象)作为比较操作即可,一般不用对 less<T> 进行特化。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: