程序员C++

Chromium智能指针使用指南

2017-11-05  本文已影响0人  爱喝咖啡的ronhu

什么是智能指针?

智能指针是一种特殊类型的“局部对象”,表现如同裸指针,但是具备离开作用域(out of scope)时主动释放所指向对象的能力。因为C++没有垃圾回收机制,因此智能指针的特性显得非常重要。

下面是最常用智能指针类型std::unique_ptr<>的例子:

  // 我们可以在构造std::unique_prt<>的时候传入指针
  std::unique_ptr value(base::JSONReader::Read(data));
  std::unique_ptr foo_ptr(new Foo(...));
  
  // ...或者使用reset()
  std::unique_ptr bar_ptr;      // 与 "Bar* bar_ptr = nullptr;" 相似.
  bar_ptr.reset(new Bar(...));  // 此时 |bar_ptr| 不为空且持有对象 
  
  // 我们可以用 () 检查std::unique_ptr<>是否为空
  if (!value)
    return false;
  
  // get() 访问持有的裸指针
  Foo* raw_ptr = foo_ptr.get();
  
  // 我们可以像使用裸指针一样调用std::unique_ptr<>的方法
  DictionaryValue* dict;
  if (!value->GetAsDictionary(&dict))
    return false;

为什么我们要使用智能指针?

即使对象的创建和析构时机不确定,使用智能指针确保我们能正确释放对象。无论方法里有再多且逻辑复杂的路径,智能指针总能确保局部变量正确的释放,且能明确对象的所有权,避免程序内存泄漏或者对象重复释放。最后,在方法调用时,需要明确指出对象拥有权的转移和结果。

存在哪些类型的智能指针?

在Chromium里最常用的两种智能指针类型是std::unique_ptr<>scoped_refptr<>。前者适用于单一所有权的对象,后者适用于引用计数的对象(然而,通常应该避免使用引用计数的对象)。如果你比较熟悉C++11,会发现scoepd_refptr<>std::shared_ptr<>用法很相似。

base/memory/ 还定义了其余几种类型的对象:

如何选择使用哪种智能指针?

不同类型指针间调用规定是怎样的?

calling conventions section of the Chromium style guide有规定。下面列出一些常用的规定。

可以通过引用传递参数或者返回值吗?

不要这样做。

原理上来说,传入const std::unique_ptr<T> &参数并且不转移所有权比传入T*有优势,这样做可以防止调用方传入错误的参数(譬如把 int 转成了 T*),而且调用方必须确保方法调用周期内传入对象不会被释放。但是,这样调用方就必须把传入对象生成在堆上,即使调用方原本可以使对象生成在栈上。这里传入裸指针相比传入const std::unique_ptr<T> &的好处是,可以将对象所有权的问题和对象生成的问题解耦。为了简洁和统一,我们避免开发人员去权衡这些利弊,总是使用裸指针就好了。

有个例外,在lambda表达式中,若将智能指针放在STL容器里作为参数传递,这里为了编译通过,必须使用const std::unique_ptr<T> &

我想使用STL容器用来持有指针对象。此时可以用智能指针吗?

可以。在C++11里,你可以将智能指针放入STL容器内。而且,不要再使用ScopedVector<T>了,使用std::vector<std::unique_ptr<T>>来替代。同样的,再也不要再使用linked_ptr<T>了,直接把智能智能放在STL容器里使用即可。

引用资料

上一篇下一篇

猜你喜欢

热点阅读