智能指针的标准之争:Boost vs. Loki

2007-04-17     推荐:39761    收藏:25726    评论:0     来源:GameRes

智能指针的标准之争:Boost vs. Loki
 
 
  2001 年10 月和2002 年4 月,在美国的华盛顿和荷兰的安的列斯群岛上分别召开了两次C++标准会议。会议的内容之一是对一项新的C++特性提议——智能指针(Smart Pointer)——进行讨论。本文将对可能成为C++新标准的两种智能指针方案(Boost vs. Loki)进行介绍和分析,并给出了相应的使用实例。

关键词:智能指针 C++ Boost Loki

  在现在的标准C++中,只有一种智能指针:std::auto_ptr。其原因并非是因为auto_ptr 已足以应付所有相关的工作——实际上,auto_ptr 有一个重大的缺陷,就是它不能被用在STL 容器中——而是因为现在的C++标准在制定时并未能对智能指针进行全面的考察。按照C++标准委员会成员Herb Sutter 的说法,只有一种标准的智能指针是一件“可羞”的事情:首先,智能指针所能做的许多有用的事情,是可怜的auto_ptr 不能完成的;其次,在有些情况下使用auto_ptr 可能会造成问题,上面所说的不能在容器中使用就是一例。实际上,许多程序员已经开发了各种有用的智能指针,有些甚至在auto_ptr 被定为标准之前就已存在,但问题是,它们不是标准的。在这样的情况下,C++标准委员会考虑引入新的智能指针,也就是自然而然的事情了。目前进入委员会视野的,主要有两种智能指针方案:Boost 智能指针和Loki 智能指针。前者是由C++标准委员会库工作组发起的Boost 组织开发的,而后者由世界级的C++专家Andrei Alexandrescu 开发,并在他所著的“Modern C++ Design”一书中进行了详细的阐释。下面,让我们分别来看一看这两种方案各自的技术特点。


一、 Boost 智能指针
Boost 的智能指针方案实现了五种智能指针模板类,每种智能指针都用于不同的目的。这五种智能指针是:

  template class scoped_ptr;
  template class scoped_array;
  template class shared_ptr;
  template class shared_array;
  template class weak_ptr;

下面将分别介绍它们各自的特性,并给出相应的使用实例:


  scoped_ptr:意在用作指向自动(栈)对象的、不可复制的智能指针。该模板类存储的是指向动态分配的对象(通过new 分配)的指针。被指向的对象保证会被删除,或是在scoped_ptr 析构时,或是通过显式地调用reset 方法。注意该模板没有“共享所有权”或是“所有权转让”语义。同时,它也是不可复制的(noncopyable)。正因为如此,在用于不应被复制的指针时,它比shared_ptr 或std:auto_ptr 要更安全。与auto_ptr一样,scoped_ptr 也不能用于STL 容器中;要满足这样的需求,应该使用shared_ptr。另外,它也不能用于存储指向动态分配的数组的指针,这样的情况应使用scoped_array。

下面是使用scoped_ptr 的一个简单实例:

class CTest
{
public:
CTest() : m_id(0) {}
CTest(int id) : m_id(id) {}
~CTest() { std::cout << "id: " << m_id << " - Destructor is being called\n"; }
void SetId(int id) { m_id = id; }
int GetId() { return m_id; }
void DoSomething()
{ std::cout << "id: " << m_id << " - Doing something\n"; }
private:
int m_id;
};
void main()
{
boost::scoped_ptr pTest(new CTest);
pTest->DoSomething();
}

其运行结果为:
  id: 0 - Doing something
  id: 0 - Destructor is being called
(以下的几个例子所用的CTest 类的定义完全相同,为节省篇幅,不再列出——作者)

显然,尽管我们自己没有调用delete,pTest 仍然为我们正确地删除了它所指向的对象。看起来scoped_ptr的用途和auto_ptr 十分类似,但实际上,scoped_ptr 类型的指针的所有权不可转让,这一点是和auto_ptr相当不同的。


  scoped_array:该模板类与scoped_ptr 类似,但意在用于数组而不是单个对象。std::vector 可用于替换scoped_array,并且远为灵活,但其效率要低一点。在不使用动态分配时,boost::array 也可用于替换scoped_array。

下面是一个使用scoped_array 的实例:

void main()
{
boost::scoped_array pTest(new CTest[2]);
pTest[0].SetId(0);
pTest[1].SetId(1);
pTest[0].DoSomething();
pTest[1].DoSomething();
std::cout << ''\n'';
}

其运行结果为:
  id: 0 - Doing something
  id: 1 - Doing something
  id: 1 - Destructor is being called
  id: 0 - Destructor is being called
scoped_array 将负责使用delete [],而不是delete 来删除它所指向的对象。


  shared_ptr:意在用于对被指向对象的所有权进行共享。与scoped_ptr 一样,被指向对象也保证会被删除,但不同的是,这将发生在最后一个指向它的shared_ptr 被销毁时,或是调用reset 方法时。shared_ptr符合C++标准库的“可复制构造”(CopyConstructible)和“可赋值”(Assignable)要求,所以可被用于标
准的库容器中。另外它还提供了比较操作符,所以可与标准库的关联容器一起工作。shared_ptr 不能用于存储指向动态分配的数组的指针,这样的情况应该使用shared_array。该模板的实现采用了引用计数技术,所以无法正确处理循环引用的情况。可以使用weak_ptr 来“打破循环”。shared_ptr 还可在多线程环境中使用。

[1] [2] [3] [4] [5] [6] 下一页

您可以针对本文进行:[评论]  [收藏]  [推荐]   [查看原文链接]  
  • 共有0条评论  点击查看更多评论
  • 网友评论仅供网友表达个人看法,并不表明e800同意其观点或证实其描述
我想发表评论:
用户名密码
  • 匿名发表
    验证码: