对下午引用计数型智能指针一文的一些补充
由于时间关系,必须冒着风雨顶着低温前往教室,所以下午并没有把想说的说完。或许也是由于没有足够的考虑。
首先为什么会产生引用计数型的智能指针,在我看来应该追溯到STL容器。由于STL的标准容器一般来说都是表达的 值语义 而非 引用语义 ,所以在我们的容器中如果要表达后者的语义就应该使用指针。
关于值语义,即STL容器将资源的管理权留给自身,让其元素随容器的生命周期消亡而消亡。比如这样的一个小程序:
struct A {
A() { printf(“A CON!/n”); }
A(const A& rhs) { printf(“A COPY CON!/N”); }
~A() { printf(“A DES!/n”); }
};
void area()
{
vector<A> avec;
A instance;
avec.push_back(instance);
}
这样的程序应该会得到这样的输出
A CON!
A COPY CON!
A DES!
A DES!
分别是第一个A实例instance构造函数,avec中将instance复制进了自身。就和函数参数值传递的意图是一样的,会经过一次复制的过程。
并且在容器离开作用域后会自动析构容器中的元素。
如果使用普通指针,可以得到我们想要的引用语义,不过可以很简单的造成资源泄漏!这里就不赘述了。
如果要使用STL容器,一般都是要求其元素是COPYABLE的,也就是STL容器需要把元素复制到自身空间内管理。所以,我们实现智能指针来实现对容器语义的扩展,给STL容器实现 引用语义。
关于Boost中的Shared_Ptr,一个简单的制造太空垃圾的程序:
class A
{
public:
A() { printf("A CONSTRUCT!"); }
~A() { printf("A DESSTRUCT!"); }
void hold(boost::shared_ptr<A> pA)
{
m_ptr = pA;
}
private:
boost::shared_ptr<A> m_ptr;
};
void area()
{
boost::shared_ptr<A> spA1(new A());
boost::shared_ptr<A> spA2(new A());
spA1->hold(spA2);
spA2->hold(spA1);
}
其也补充了我下午博文中出现的两者循环引用的例子。
如果是普通的设计中,可以使用普通的指针来表示 聚合 关系。这样也给了我们一定的灵活性,来自己施放和管理对象的生命期(比如在析构函数中delete或不delete这个普通的指针,但是不delete可能会出现泄漏,如果delete可能会使外界的指针失效……一切都在程序员自己选择!)。