Memory (C++标准库)

memory 是C++标准程式库中的一个头文件，定义了C++标准中的智能指针、内存分配器（allocator）、与垃圾回收有关的函数、临时性的申请与释放动态内存的函数、在内存上创建（构造）对象的函数等等。
智能指针.
智能指针是指当指针对象的生命期结束析构时，同时把指针所指的对象也delete或者引用计数减1。
unique_ptr.
unique_ptr是个类模板。unique_ptr指针对象独占式地引用所指的数据对象。不能复制构造（copy ctor），也不能复制赋值，也就是对其无法进行复制，不能得到指向同一个对象的两个unique_ptr；但是可以移动构造和移动赋值。当unique_ptr指针对象离开其作用域，生命期结束时，自动使用内部给定的删除器（deleter）delete所指向的数据对象。unique_ptr十分依赖于右值引用和移动语义。
template&lt;class Type, class Del = default_delete&lt;Type&gt; &gt;
 class unique_ptr {
public:
 typedef Type element_type; //指针基类型
 typedef Del deleter_type; //析构类型
 typedef T1 pointer; //指针类型 为Del::pointer，否则为Type *
//构造函数
 unique_ptr (); //11 空指针
 unique_ptr (nullptr_t _Nptr); //22 空指针
 explicit unique_ptr (pointer _Ptr); //33
 unique_ptr (pointer _Ptr, typename conditional&lt;is_reference&lt;Del&gt;::value, Del,typename add_reference&lt;const Del&gt;::type&gt;::type _Deleter); //44
 unique_ptr (pointer _Ptr,typename remove_reference&lt;Del&gt;::type&amp;&amp; _Deleter); //55
 unique_ptr (unique_ptr&amp;&amp; _Right); //66
 template&lt;class Type2, Class Del2&gt; unique_ptr (unique_ptr&lt;Type2, Del2&gt;&amp;&amp; _Right); //77
//析构函数
 ~unique_ptr ();
 unique_ptr&amp; operator= (unique_ptr&amp;&amp; _Right); //右值赋值
 template&lt;class Type2, Class Del2&gt; unique_ptr&amp; operator= (unique_ptr&lt;Type2, Del2&gt;&amp;&amp; _Right);//右值赋值
 void swap (unique_ptr&amp; _Right); //交换两个unique_ptr对象的内容
 pointer release (); //在stored_ptr中存储pointer的新的值，并返回前一个值，用于放弃对所指数据对象的独占
 void reset (pointer _Ptr = pointer() ); //delete当前拥有的资源并接受新的资源
 pointer get () const; //返回stored_ptr
 Type&amp; operator* () const; //返回*stored_ptr
 pointer operator-&gt; () const; //返回stored_ptr
 Del&amp; get_deleter (); //返回stored_deleter的引用
 const Del&amp; get_deleter () const; //返回stored_deleter
 explicit operator bool () const; //get() != pointer() 的值
 unique_ptr(const unique_ptr&amp; _Right) = delete;
 unique_ptr&amp; operator=(const unique_ptr&amp; _Right) = delete;
private:
 pointer stored_ptr; // exposition only
 Del stored_deleter; // exposition only
unique_ptr的主要用途有：
shared_ptr.
shared_ptr是一个类模板，包装了使用引用计数的智能指针。当shared_ptr在退出其作用域、生命期结束时，析构函数或自动对所指内存数据对象的引用计数减去1。如果内存数据对象的引用计数为0，则会被自动delete。指向同一资源的shared_ptr共同拥有一个控制块，其中保存了shared_ptr的引用计数、指向这一资源的weak_ptr的数目、资源的析构器（deleter ）地址、对该控制块的可定制的allocator。
template&lt;class Ty&gt;
 class shared_ptr {
public:
 typedef Ty element_type; //指针基类型
//构造函数
 shared_ptr(); //11 空指针
 shared_ptr(nullptr_t); //22 空指针
 shared_ptr(const shared_ptr&amp; sp); //33 拷贝构造
 shared_ptr(shared_ptr&amp;&amp; sp); //44 右值移动构造
 template&lt;class Other&gt; explicit shared_ptr(Other * ptr); //55 由其他指针初始化，构造失败时自动调用delete ptr
 template&lt;class Other, class D&gt; shared_ptr(Other * ptr, D dtor); //66 由其他指针初始化，dtor是个可调用的函数对象，构造失败时自动调用dtor(ptr)
 template&lt;class D&gt; shared_ptr(nullptr_t, D dtor); //77 空指针，并指定deleter
 template&lt;class Other, class D, class A&gt; shared_ptr(Other *ptr, D dtor, A alloc);//88 alloc管理shared_ptr控制块的内存分配与释放，构造失败时自动调用dtor(ptr)
 template&lt;class D, class A&gt; shared_ptr(nullptr_t, D dtor, A alloc);//99 空指针
 template&lt;class Other&gt; shared_ptr(const shared_ptr&lt;Other&gt;&amp; sp); //0A 拷贝构造+类型转换
 template&lt;class Other&gt; shared_ptr(const shared_ptr&lt;Other&gt;&amp;&amp; sp); //0B 移动构造+类型转换
 template&lt;class Other&gt; explicit shared_ptr(const weak_ptr&lt;Other&gt;&amp; wp); //0C 由弱指针拷贝构造
 template&lt;class Other&gt; shared_ptr(auto_ptr&lt;Other&gt;&amp; ap); //0D 由auto_ptr指针拷贝构造
 template&lt;class Other, class D&gt; shared_ptr(unique_ptr&lt;Other, D&gt;&amp;&amp; up); //0E 由unique_ptr移动构造
 template&lt;class Other&gt; shared_ptr(const shared_ptr&lt;Other&gt;&amp; sp, Ty *ptr); //0F 
 template&lt;class Other, class D&gt;shared_ptr(const unique_ptr&lt;Other, D&gt;&amp; up) = delete;//10 禁用const unique_ptr作为移动构造函数
 ~shared_ptr(); // 析构函数
 shared_ptr&amp; operator=(const shared_ptr&amp; sp); //赋值运算符
 template&lt;class Other&gt; shared_ptr&amp; operator=(const shared_ptr&lt;Other&gt;&amp; sp); //类型转换的赋值运算符
 shared_ptr&amp; operator=(shared_ptr&amp;&amp; sp); //右值引用的移动语义
 template&lt;class Other&gt; shared_ptr&amp; operator=(shared_ptr&lt;Other&gt;&amp;&amp; sp); //右值引用+类型转换
 template&lt;class Other&gt; shared_ptr&amp; operator=(auto_ptr&lt; Other &gt;&amp;&amp; ap); //右值引用+auto_ptr类型转换
 template &lt;class Other, class D&gt; shared_ptr&amp; operator=(const unique_ptr&lt; Other, D&gt;&amp; up) = delete; //禁止const型unique_ptr移动赋值给shared_ptr
 template &lt;class Other, class D&gt; shared_ptr&amp; operator=(unique_ptr&lt;Other, D&gt;&amp;&amp; up);//右值引用的移动语义+类型转换
 void swap(shared_ptr&amp; sp); //交换两个指针的内容
//reset成员函数，把当前指向的数据对象的引用计数减1，然后指向参数表中新的数据对象
 void reset(); 
 template&lt;class Other&gt; void reset(Other *ptr);
 template&lt;class Other, class D&gt; void reset(Other *ptr, D dtor);
 template&lt;class Other, class D, class A&gt; void reset(Other *ptr, D dtor, A alloc);
 Ty *get() const; //返回所指向的数据对象的地址
 Ty&amp; operator*() const; //返回所指向的数据对象
 Ty *operator-&gt;() const; //返回所指向的数据对象的地址
 long use_count() const; //返回引用计数值
 bool unique() const; //判断是否独占引用数据对象
 operator bool() const; //判断是否指向了一个数据对象
 template&lt;class Other&gt; bool owner_before(shared_ptr&lt;Other&gt; const&amp; ptr) const;
 template&lt;class Other&gt; bool owner_before(weak_ptr&lt;Other&gt; const&amp; ptr) const;
 template&lt;class D, class Ty&gt; D* get_deleter(shared_ptr&lt;Ty&gt; const&amp; ptr);
weak_ptr.
弱指针weak_ptr用于指向、但不拥有（即不参加引用计数）由shared_ptr管理的资源。弱指针并不直接提供对资源的访问。应该通过shared_ptr来访问资源。当资源的引用计数为0（所有拥有该资源的shared_ptr对象都已被销毁），该资源将被delete，这时如果仍然有弱指针指向该资源，则该弱指针将变为expired状态。这实际上避免了资源的循环引用计数。对于循环的引用计数，如果把其中的一个shared_ptr的指针指向改为weak_ptr的指针指向，即打破了循环引用。
template&lt;class Ty&gt; class weak_ptr {
public:
 typedef Ty element_type; //指针基类型
//构造函数
 weak_ptr(); //空指针
 weak_ptr(const weak_ptr&amp;); //拷贝构造
 template&lt;class Other&gt; weak_ptr(const weak_ptr&lt;Other&gt;&amp;); //类型转换的拷贝构造
 template&lt;class Other&gt; weak_ptr(const shared_ptr&lt;Other&gt;&amp;); //从shared_ptr拷贝构造
//赋值运算符
 weak_ptr&amp; operator=(const weak_ptr&amp;);
 template&lt;class Other&gt; weak_ptr&amp; operator=(const weak_ptr&lt;Other&gt;&amp;);
 template&lt;class Other&gt; weak_ptr&amp; operator=(shared_ptr&lt;Other&gt;&amp;);
 void swap(weak_ptr&amp;); //交换对象的内容
 void reset(); //放弃指向资源，当前对象变为空的弱指针
 long use_count() const; //返回资源的引用计数
 bool expired() const; //判断指向的资源是否还存在（或已经被释放）
 shared_ptr&lt;Ty&gt; lock() const; // 获取对资源的专属拥有
auto_ptr.
auto_ptr，即自动指针，在C++11标准是过时的类模板。
其他Helper类.
default_delete.
作为使用codice_1分配内存的unique_ptr对象的deleter。有两种形式：
示例：
int main()
// {
// std::shared_ptr&lt;int&gt; shared_bad(new int[10]);
// } // the destructor calls delete, undefined behavior
 {
 std::shared_ptr&lt;int&gt; shared_good(new int[10], std::default_delete&lt;int[]&gt;
 } // the destructor calls delete[], ok
 {
 std::unique_ptr&lt;int&gt; ptr(new int(5));
 } // unique_ptr&lt;int&gt; uses default_delete&lt;int&gt;
 {
 std::unique_ptr&lt;int[]&gt; ptr(new int[10]);
 } // unique_ptr&lt;int[]&gt; uses default_delete&lt;int[]&gt;
 // default_delete can be used anywhere a delete functor is needed
 std::vector&lt;int*&gt; v;
 for(int n = 0; n &lt; 100; ++n)
 v.push_back(new int(n));
 std::for_each(v.begin(), v.end(), std::default_delete&lt;int&gt;());
allocator.
allocator是STL中非常常用的类模板，用于定制内存的分配、释放、管理。目的是封装STL容器在内存管理上的低层细节，所以用户程序不应该直接调用allocator去管理内存，除非是正在定制容器。allocator将内存的分配与对象的构造初始化解耦，分别用allocate、construct两个成员函数完成；同样将内存的释放与对象的析构销毁解耦，分别用deallocat、destroy两个成员函数完成。自定义的allocator的实现，必须满足C++11标准的17.6.3.5节中的“Table 28 —— Allocator requirements”，简单说就是要在类中定义若干类型名、模板成员名、成员函数、运算符函数。codice_2中定义的allocator类模板做一些使用全局malloc/free函数表达式的内存的分配、释放的平常操作：
template&lt;class _Ty&gt; class allocator : public _Allocator_base&lt;_Ty&gt;
public:
/*类型定义。容器类常常直接从它的allocator提取这些类型—— */
typedef _Allocator_base&lt;_Ty&gt; _Mybase; //基类型
 typedef typename _Mybase::value_type value_type;//值类型
 typedef value_type _FARQ *pointer; //指针类型
 typedef value_type _FARQ&amp; reference; //引用类型
 typedef const value_type _FARQ *const_pointer; //常量指针类型
 typedef const value_type _FARQ&amp; const_reference;//常量引用类型
 typedef size_t size_type; //size类型
 typedef ptrdiff_t difference_type; //地址差值类型
/*类型操作函数： */ 
 template&lt;class _Other&gt;
 struct rebind //用于重绑定的成员模板： convert this type to allocator&lt;_Other&gt;。
 //因为容器类需要动态申请内存的往往不是value_type，而是诸如List Node这样的其他类型
 typedef allocator&lt;_Other&gt; other;
 pointer address(reference _Val) const
 { // 把mutuable引用变换为地址返回
 return ((pointer) &amp;(char&amp;)_Val);
 const_pointer address(const_reference _Val) const
 { //把只读引用变换为只读地址返回
 return ((const_pointer) &amp;(char&amp;)_Val);
/*构造函数：*/ 
 allocator() throw( )
 { //缺省构造，不抛出异常
 allocator(const allocator&lt;_Ty&gt;&amp;) throw()
 { // 空的拷贝构造
 template&lt;class _Other&gt;
 allocator(const allocator&lt;_Other&gt;&amp;) throw()
 { //从相关的allocator做拷贝构造，内容为空
 template&lt;class _Other&gt;
 allocator&lt;_Ty&gt;&amp; operator=(const allocator&lt;_Other&gt;&amp;)
 { //从相关的allocator做拷贝赋值运算符，内容为空
 return (*this);
/*以下为业务函数： */
 void deallocate(pointer _Ptr, size_type) //释放内存，并不析构对象。第二个参数为元素的项数
 { // deallocate object at _Ptr, ignore size 
 ::operator delete(_Ptr);
 pointer allocate(size_type _Count) //获取内存资源，并不调用对象的构造函数
 { // allocate array of _Count elements
 return (_Allocate(_Count, (pointer)0)); 
 pointer allocate(size_type _Count, const void _FARQ *)
 { // allocate array of _Count elements, ignore hint 为高性能而设计的allocator可能会利用第二个参数的提示
 return (allocate(_Count));
 void construct(pointer _Ptr, const _Ty&amp; _Val) // construct object at _Ptr with value _Val 
 { //实际上调用了“带位置的new运算符表达式”，实现在特定位置上调用构造函数。 
 _Construct(_Ptr, _Val);
 void construct(pointer _Ptr, _Ty&amp;&amp; _Val) //construct object at _Ptr with right-value _Val
 { 实际上调用了“带位置的new运算符表达式”，以及右值完美转发，实现在特定位置上调用构造函数。
 ::new ((void _FARQ *)_Ptr) _Ty(_STD forward&lt;_Ty&gt;(_Val));
 template&lt;class _Other&gt;
 void construct(pointer _Ptr, _Other&amp;&amp; _Val) // construct object at _Ptr with value _Val， 带类型转换
 ::new ((void _FARQ *)_Ptr) _Ty(_STD forward&lt;_Other&gt;(_Val));
 void destroy(pointer _Ptr)
 { // 摧毁在地址 _Ptr的对象，但不释放内存
 _Destroy(_Ptr);
 _SIZT max_size() const _THROW0()
 { // 估计allocator能分配的数据对象的最大可能数目
 _SIZT _Count = (_SIZT)(-1) / sizeof (_Ty);
 return (0 &lt; _Count ? _Count : 1);
};
allocator_traits.
allocator_traits是对allocator的包装。
bad_weak_ptr.
bad_weak_ptr是个异常类。在用弱指针拷贝构造共享指针时，如果弱指针是expired，那么拷贝构造函数抛出bad_weak_ptr异常。
enable_shared_from_this.
enable_shared_from_this是一个helper类模板，用于作为数据类的基类。当数据类的对象已经被shared_ptr所拥有，如果需要从该数据类对象获得其shared_ptr指针，就需要调用作为基类的enable_shared_from_this的成员函数codice_3。例如：
struct Data : public enable_shared_from_this&lt;Data&gt; { };
int main() {
 shared_ptr&lt;Data&gt; a (new Data);
 Data&amp; r = *a;
 shared_ptr&lt;Data&gt; b = r.shared_from_this(); 
在上例中，b与a共同拥有对数据类对象的同一套引用计数，因此是正确的。如果如此构造b：
则对同一个数据类对象，弄出了两套引用计数。这会导致当一套引用计数变为0而销毁数据类对象时，另外一套引用计数的shared_ptr成为“悬空”的错误。
Microsoft Visual C++ 2010是在enable_shared_from_this类模板中定义一个数据类型codice_5。shared_ptr的对象在调用构造函数时，最后将调用一个函数_Enable_shared(_Ty *_Ptr, _Ref_count_base *_Refptr），其中第一个参数是数据类对象的指针，第二个参数是引用计数控制块的指针。利用模板元编程的参数推导的特性，编译器选择_Enable_shared，或是匹配下述模板函数
或是匹配下述普通函数
前者把enable_shared_from_this类中把一个弱指针指向了shared_ptr的引用计数控制块。从而实现了enable_shared_from_this类的语义。
pointer_traits.
pointer_traits是一个类模板，描述指针类型所需要的一些类型的定义。
raw_storage_iterator.
raw_storage_iterator是个类模板，用于表示指向内存的一个前向迭代器。其赋值运算符在当前所指向内存上调用值类型的构造函数，生成一个对象。
例子.
共享指针.
class Test
public:
 Test()
 std::cout « "Test()" « std::endl;
 ~Test()
 std::cout « "~Test()" « std::endl;
};
int main()
 std::shared_ptr&lt;Test&gt; p1 = std::make_shared&lt;Test&gt;();
 std::cout « "1 ref:" « p1.use_count() « std::endl;
 std::shared_ptr&lt;Test&gt; p2 = p1;
 std::cout « "2 ref:" « p1.use_count() « std::endl;
 std::cout « "3 ref:" « p1.use_count() « std::endl;
 return 0;
弱指针例子.
class TestB;
class TestA
public:
 TestA()
 std::cout « "TestA()" « std::endl;
 void ReferTestB(std::shared_ptr&lt;TestB&gt; test_ptr)
 m_TestB_Ptr = test_ptr;
 void TestWork()
 std::cout « "~TestA::TestWork()" « std::endl;
 ~TestA()
 std::cout « "~TestA()" « std::endl;
private:
 std::weak_ptr&lt;TestB&gt; m_TestB_Ptr;
class TestB
public:
 TestB()
 std::cout « "TestB()" « std::endl;
 void ReferTestB(std::shared_ptr&lt;TestA&gt; test_ptr)
 m_TestA_Ptr = test_ptr;
 void TestWork()
 std::cout « "~TestB::TestWork()" « std::endl;
 ~TestB()
 ////把std::weak_ptr类型转换成std::shared_ptr类型
 std::shared_ptr&lt;TestA&gt; tmp = m_TestA_Ptr.lock();
 tmp-&gt;TestWork();
 std::cout « "2 ref a:" « tmp.use_count() « std::endl;
 std::cout « "~TestB()" « std::endl;
 std::weak_ptr&lt;TestA&gt; m_TestA_Ptr;
int main()
 std::shared_ptr&lt;TestA&gt; ptr_a = std::make_shared&lt;TestA&gt;();
 std::shared_ptr&lt;TestB&gt; ptr_b = std::make_shared&lt;TestB&gt;();
 ptr_a-&gt;ReferTestB(ptr_b);
 ptr_b-&gt;ReferTestB(ptr_a);
 std::cout « "1 ref a:" « ptr_a.use_count() « std::endl;
 std::cout « "1 ref b:" « ptr_a.use_count() « std::endl;
 return 0;
独占指针的例子.
int main()
 std::unique_ptr&lt;int&gt; pInt;
 pInt.reset(new int());
 int *p = pInt.release(); //释放所有权
 //由于unique_ptr有std::unique_ptr&lt;T[]&gt;的重载函数，所以它可以用来管理数组资源
 std::unique_ptr&lt;int[]&gt; pArray(new int[3]{1,3,3});