智能指针(现代C++)
标准库包含在现代的 C++ 编程中, 聪明指针,用于帮助确保该程序将是可用的内存和资源泄漏并安全异常。
使用智能指针
聪明指针是在std命名空间中的<memory>头文件。它们是相当重要 RAII 或资源收购了 Initialialization 编程的方法。此方法的主要目标是确保资源收购初始化该对象,以便创建和准备就绪在一行代码中的对象的所有资源的同时发生。在实际情况下,RAII 的主要原则是为其授予任何的所有权堆分配的资源 — — 例如,动态分配内存或系统对象句柄 — 堆栈分配的对象的析构函数中包含代码删除或释放该资源以及任何关联的清理代码。
在大多数情况下,初始化原始的指针或资源句柄指向实际资源,将指针滑到智能指针立即。在现代的 C++ 中,仅在有限范围、 循环或帮助器函数性能是至关重要的并没有所有权混乱的可能性较小的代码块中使用原始指针。
下面的示例比较原始指针声明为智能指针声明。
void UseRawPointer()
{
// Using a raw pointer -- not recommended.
Song* pSong = new Song(L"Nothing on You", L"Bruno Mars");
// Use pSong...
// Don't forget to delete!
delete pSong;
}
void UseSmartPointer()
{
// Declare a smart pointer on stack and pass it the raw pointer.
unique_ptr<Song> song2(new Song(L"Nothing on You", L"Bruno Mars"));
// Use song2...
wstring s = song2->duration_;
//...
} // song2 is deleted automatically here.
如示例中所示,智能指针是在堆栈上声明并初始化使用原始指针指向堆分配的对象的类模板。智能指针初始化后,它拥有原始指针。这意味着智能指针负责删除原始指针指定的内存。智能指针析构函数包含要删除,请调用,智能指针堆栈上声明的因为其析构函数调用时智能鼠标指针离开作用域,即使某处进一步沿堆栈向上,则引发异常。
封装的指针访问,请使用熟悉的指针运算符->和*,智能指针类重复返回封装原始指针。
C + + 智能指针方法类似于语言 (如 C# 中创建的对象: 创建对象,然后让系统负责在恰当的时候将其删除。不同的是没有单独的垃圾回收器在后台 ; 运行 通过标准 C++ 范围规则,以便在运行时环境是更快、 更高效地管理内存。
重要事项 |
---|
始终位于单独的一行代码,永远不会在参数列表中,创建智能指针,以便由于某些参数列表分配规则将不会发生了细微的资源短缺的现象。 |
下面的示例演示如何unique_ptr标准模板库中的智能指针类型无法用于封装到大型对象的指针。
class LargeObject
{
public:
void DoSomething(){}
};
void ProcessLargeObject(const LargeObject& lo){}
void SmartPointerDemo()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
//Call a method on the object
pLarge->DoSomething();
// Pass a reference to a method.
ProcessLargeObject(*pLarge);
} //pLarge is deleted automatically when function block goes out of scope.
该示例演示使用智能指针的下列基本步骤。
将智能鼠标指针声明为自动 (本地) 的变量中。(不要使用new或malloc在智能指针本身的表达式。)
在类型参数中指定封装指针指向的类型。
若要将一个原始指针传递new-ed 智能指针构造函数中的对象。(某些实用程序函数或智能指针构造函数执行该操作为您。)
使用重载->和*运算符访问该对象。
使智能删除对象的指针。
聪明指针被为了尽可能同时在内存和性能方面的效率。例如中的唯一数据成员unique_ptr是封装的指针。这意味着, unique_ptr ,4 个字节或 8 个字节的指针的大小完全相同。通过使用智能指针重载访问封装的指针 * 和-> 运算符不明显慢于直接访问原始的指针。
智能指针有他们自己的成员函数,这可以通过使用"点"表示法。例如,某些 STL 聪明指针必须重置成员函数释放鼠标指针的所有权。如果要释放内存所拥有的智能指针之前智能指针超出范围,如下面的示例中所示,这非常有用。
void SmartPointerDemo2()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
//Call a method on the object
pLarge->DoSomething();
// Free the memory before we exit function block.
pLarge.reset();
// Do some other work...
}
聪明指针通常提供直接访问其原始指针的方法。STL 智能指针有get成员函数实现此目的,和CComPtr有一个公共p类成员。通过提供直接访问底层的指针,可以管理您自己的代码中的内存,并仍将原始指针传递给不支持智能指针的代码中使用智能指针。
void SmartPointerDemo4()
{
// Create the object and pass it to a smart pointer
std::unique_ptr<LargeObject> pLarge(new LargeObject());
//Call a method on the object
pLarge->DoSomething();
// Pass raw pointer to a legacy API
LegacyLargeObjectFunction(pLarge.get());
}
类智能指针
下一节概述了不同类型的 Windows 编程环境中提供智能指针,并描述了何时使用它们。
C + + 标准库聪明指针
这些智能指针用作第一个选项的封装到普通旧 C++ 对象 (POCO) 的指针。unique_ptr
使基础指针的一个所有者。除非您确实知道您需要使用作为默认选项的 POCO shared_ptr。可以移动到一个新的所有者,但不是复制或共享。将替换auto_ptr,它已被否决。若要比较boost::scoped_ptr。unique_ptr是小而且高效。 大小是一个指针,它支持快速插入和 STL 集合中的检索的 rvalue 引用。头文件: <memory>。有关更多信息,请参见如何:创建和使用unique_ptr实例和 unique_ptr Class。shared_ptr
引用计数智能指针。如果要将一个原始指针指定给多个所有者,例如,当您从容器中返回的指针副本,但希望保留原始的使用。不会删除原始指针直到所有shared_ptr所有者已超出范围或已超越所有权。Size 是两个指针。 一个对象,一个用于包含的引用计数的共享的控制块。头文件: <memory>。有关更多信息,请参见如何:创建和使用shared_ptr实例和 shared_ptr Class。weak_ptr
与一起使用的特殊情况智能指针shared_ptr。A weak_ptr提供了由一个或多个对象的访问shared_ptr实例,但不会参与引用计数。当您需要观察一个对象,但不是需要它保持活动状态时使用。在某些情况下中断之间的循环引用所需shared_ptr实例。头文件: <memory>。有关更多信息,请参见如何:创建和使用weak_ptr实例和 weak_ptr Class。
聪明指针的 COM 对象 (经典 Windows 编程)
时使用的 COM 对象,请在相应的智能指针类型包装接口指针。活动模板库 (ATL) 定义了几种聪明指针,出于不同目的。您还可以使用**_com_ptr_t**的.tlb 文件从创建包装类时,编译器使用智能指针类型。当您不希望包含 ATL 头文件时,它是最佳选择。CComPtr 类
使用此步骤,除非您不能使用 ATL.执行引用计数通过使用AddRef和Release的方法。有关更多信息,请参见 如何:创建和使用CComPtr和CComQIPtr实例。CComQIPtr 类
类似于CComPtr电话还提供了简化的语法,但QueryInterface上的 COM 对象。有关更多信息,请参见 如何:创建和使用CComPtr和CComQIPtr实例。CComHeapPtr 类
要使用的对象的智能指针CoTaskMemFree以释放内存。CComGITPtr 类
智能全局接口表 (GIT) 中获取接口的指针。_com_ptr_t选件类
类似于CComQIPtr的功能,但并不依赖于 ATL 标头。
ATL 智能 POCO 对象指针
除了为 COM 对象的智能指针,ATL 还定义智能指针和智能指针,旧的纯 C++ 对象的集合。在传统 Windows 编程中,这些类型是很有用的备用方案的 STL 集合,尤其是当代码可移植性,则不需要或不想混合 STL 和 ATL.的编程模型CAutoPtr 类
强制实施唯一所有权转让所有权副本上的智能指针。不建议使用与相当std::auto_ptr类。CHeapPtr 类
智能指针的对象分配的使用 C malloc函数。CAutoVectorPtr 类
为阵列分配使用智能指针new[]。CAutoPtrArray 类
封装的数组的类CAutoPtr元素。CAutoPtrList 类
封装用于操作的列表的方法的类CAutoPtr节点。