C++标准模板库是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的,C++标准模板库在C++中的应用十分广泛,这项技术在引进C++之前已经使用很久了。
我们会假设一个失败的资源分配会导致一个异常--事实上,这会经常的发生。所以如果你想试图用一个石头打两只鸟的话,或者在一个构造函数中申请两种形式的资源,你可能就会陷入麻烦。
只要想想在一种资源分配成功但另一种失败抛出异常时会发生什么。因为构造函数还没有全部完成,析构函数不可能被调用,第一种资源就会发生泄露。这种情况可以非常简单的避免。无论何时你有一个需要两种以上资源的类时,写两个笑的封装器将它们嵌入你的类中。每一个嵌入的构造都可以保证删除,即使包装类没有构造完成。
我们至今还没有讨论最常见类型的资源--用操作符new分配,此后用指针访问的一个对象。我们需要为每个对象分别定义一个封装类吗?(事实上,C++标准模板库已经有了一个模板类,叫做auto_ptr,其作用就是提供这种封装。我们一会儿在回到auto_ptr。)让我们从一个极其简单、呆板但安全的东西开始。看下面的Smart Pointer模板类,它十分坚固,甚至无法实现。
- class Lock
- {
- public:
- Lock (CritSect& critSect)
- : _critSect (critSect)
- {
- _critSect.Acquire ();
- }
- ~Lock ()
- {
- _critSect.Release ();
- }
- private
- CritSect & _critSect;
- };
- 锁一般的用法如下:
- void Shared::Act () throw (char *)
- {
- Lock lock (_critSect);
- // perform action -- may throw
- // automatic destructor of lock
- }
为什么要把SPtr的构造函数设计为protected呢?如果我需要遵守第一条规则,那么我就必须这样做。资源--在这里是class T的一个对象--必须在封装器的构造函数中分配。但是我不能只简单的调用new T,因为我不知道T的构造函数的参数。
因为,在原则上,每一个T都有一个不同的构造函数;我需要为他定义个另外一个封装器。C++标准模板库的用处会很大,为每一个新的类,我可以通过继承SPtr定义一个新的封装器,并且提供一个特定的构造函数。
同样的,你也可以再你的代码中用加强Release的可靠性。相应的Pop方法要做些什么呢?他应该释放了资源并祈祷调用它的是一个负责的人而且立即作一个资源传递它到一个Smart Pointer?这听起来并不好。
资源管理在内容索引(Windows NT Server上的一部分,现在是Windows 2000)上工作,并且,我对这十分满意。然后我开始想……这一方法是在这样一个完整的系统中形成的,如果可以把它内建入语言的本身岂不是一件非常好?我提出了强指针(Strong Pointer)和弱指针(Weak Pointer)。
一个Strong Pointer会在许多地方和我们这个SPtr相似--它在超出它的作用域后会清除他所指向的对象。资源传递会以强指针赋值的形式进行。也可以有Weak Pointer存在,它们用来访问对象而不需要所有对象--比如可赋值的引用。
任何C++标准模板库都必须声明为Strong或者Weak,并且语言应该来关注类型转换的规定。例如,你不可以将Weak Pointer传递到一个需要Strong Pointer的地方,但是相反却可以。Push方法可以接受一个Strong Pointer并且将它转移到Stack中的Strong Pointer的序列中。Pop方法将会返回一个Strong Pointer。把Strong Pointer的引入语言将会使垃圾回收成为历史。
【编辑推荐】