//1.标准库提供了两种智能指针类型来管理动态对象,均定义在头文件memory中,声明在std命名空间。
// shared_ptr:允许多个指针指向同一个对象。
// unique_ptr:独占所指的对象。
// 标准库还定义了weak_ptr的伴随类,它是一种弱作用。指向shared_ptr所管理的对象。 //2.shared_ptr和unique_ptr均支持的操作:
shared_ptr<T> sp
unique_ptr<T> up:空智能指针,指向类型为T的对象
p :将p用作一个判断条件,若p指向一个对象,则为true
*p, p->men :得到p所指向的对象
p.get() :返回p中保存的指针。
swap(p, q)
p.swap(q) :交换p和q的指针 //3.shared_ptr独有的操作:
make_shared<T>(args) :返回一个shared_ptr,指向一个动态分配的类型为T的对象。使用args初始化此对象。是安全的分配和使用动态内存的方法。其本身也是一个模板。
shared_ptr<T> p(q) :p是q的拷贝,此操作会递增q的计数器,q中的指针必须能转为T。
p = q :p和q都是shared_ptr,p的指针必须能指向q所指的对象,此操作会递减p的引用计数,递增q的引用计数。当p的引用计数变为0的时候则释放其管理的内存。
shared_ptr<const int> pInt(new int());
shared_ptr<int> pInt1;
pInt1 = pInt; //错误
pInt = pInt1; //正确
p.unique() :若p的引用计数为1,则返回true,否则返回false
p.use_count() :可能很慢,主要用于调试,返回与p共享对象的智能指针的数量 //4.当在容器中使用了shared_ptr,当不在需要容器中的全部元素的时候,记得用erase删除不再需要的元素。 //5.new和delete:
.在自由空间分配的内存是无名的,因此new无法为其分配的对象命名,而是返回一个指向该对象的指针。
.默认情况下,动态分配的对象是默认初始化的。
.可以采用直接初始化或值初始化的方式,方法是使用()。直接初始化:int *pValue = new int(); 值初始化:int *pValue = new int();
.默认情况下,new失败时候会抛出bad_alloc异常。使用定位new可以避免抛出异常:int *pValue = new (nothrow)int;当分配内存失败的时候,pValue将是一个空指针。nothrow定义在头文件new中,声明在命名空间std中。
.传递给delete的指针必须是动态分配的指针或者是空指针。多次释放相同的指针的行为是未定义的。
.在使用了delete的时候,最好将被操作的指针置空。 //6.可以用new返回的指针来直接初始化shared_ptr,此构造函数是explicit的,所以只能采用直接初始化的方式。 //7.不要用智能指针的get()函数得到的指针去初始化另一个智能指针,否则会导致多次delete同一块内存。
// shared_ptr类的reset成员函数可以将一个新的指针赋予shared_ptr,如果需要的话会释放其原来指向的内存。
// shared_ptr类默认使用delete来充当删除器。可以为shared_ptr对象指定自己的删除器。 //8.智能指针的使用规范:
// A:不使用相同的内置指针初始化或reset多个智能指针
// B:不delete get()返回的指针
// C:不使用get()初始化或reset另一个智能指针
// D:在使用get()返回的指针的时候,要记住当对应的最后一个智能指针销毁后,这个指针就无效了。
// E:在使用shared_ptr的时候,当管理的资源不是new分配的时候,要传递给其一个删除器。 //9.unique_ptr:其有一个可以接受内置指针的构造函数,是explicit的,所以当使用内置指针初始化unique_ptr的时候要采用直接初始化。 //10.unique_ptr的操作:
u = nullptr :将对象置空并释放其资源
u.release() :u放弃对指针的控制权,返回指针并且将u置空
u.reset() :释放u指向的对象,并将u置空
u.reset(q) :释放u指向的对象,并将u指向内置指针q
u.reset(nullptr):释放u指向的对象,并将u置空
// 虽然不能拷贝或赋值unique_ptr,但是可以通过release和reset来将指针的控制权由一个unique(非const)转移到另一个unique: p.reset(p1.release()); //11.不能拷贝或赋值unique_ptr的规则有一个例外:可以拷贝或赋值一个将要被销毁的unique_ptr:比如从函数返回一个unique_ptr,返回局部unique_ptr对象。
unique_ptr<int> fun() {unique_ptr<int> p(new int()); return p;}
unique_ptr<int> p = fun();//p = unique_ptr 10 //12.weak_ptr是一种不控制指向对象生存期的智能指针,它指向一个由shared_ptr管理的对象。将一个weak_ptr绑定到一个shared_ptr上不会影响后者的使用计数。
w = p :p可以是一个shared_ptr对象或者是weak_ptr对象。赋值后w将共享p的对象
w.reset() :将w置空
w.use_count():与w共享对象的shared_ptr的数量
w.expired() :若w.use_count()为0,则返回true,否则返回false expire[ex·pire || ɪk'spaɪə]v.期满,断气,
w.lock() :如果w.expired()为true,返回一个空的shared_ptr,否则返回一个指向w的对象的shared_ptr。
// 由于对象可能不存在,所以weak_ptr不能直接访问对象,而要通过lock()函数。 //13.分配动态数组内存的时候,分配的大小为0也是允许的,但是不能对此指针进行解引用(vs2010下可以对其解引用,但是最好别用)。对于动态数组不能应用begin()和end()。要搭配使用delete[]。
// delete[]是按照逆序释放内存的。分配动态数组的时候可以使用值初始化,但是不能给出初始化器(这个特性导致无法使用new[]来为没有默认构造函数的类型分配动态数组)。int *p = new int[10]();是可以的。int *p = new int[10](0);是不可以的。 //14.使用unique_ptr可以管理一个动态数组,必须在类型后跟一对尖括号:unique_ptr<int []> pInt(new int[10]());在销毁pInt的时候,会自动使用delete[];
// 与unique_ptr不同,shared_ptr不直接支持管理动态数组。如果希望使用shared_ptr管理动态数组,必须提供自定义的删除器。shared_ptr<int> pInt(new int[10](), [](int *p){delete []p;});
// unique_ptr支持直接管理动态数组,其提供了下标运算符。对应的,shared_ptr不支持直接管理动态数组,其不支持下标运算符,只能通过其get()函数得到对象的指针,通过指针偏移的方式去访问动态数组中的对象。 //15.当分配一大块内存的时候,我们通常计划在这块内存上按需构造对象。在此情况下,我们希望将内存分配和对象构造分离,这意味着我们可以分配大块内存,但是只在真正需要时才真正执行对象创建操作。
// 标准库allocator类定义在头文件memory中,声明在命名空间std中。它可以将内存分配和对象构造分离开来。其本身是一个类模板,会根据给定的对象类型来确定恰当的内存大小和对齐位置。
class CTest
{
public:
CTest(int i) : value(i){}
public:
int value;
};
allocator<CTest> allocTest;
CTest *p = allocTest.allocate(); //分配一段原始的未经构造的内存。指针p所指向40字节的内存是未经构造的
int value = p[].value; //value = -842150451。还未构造对象的情况下使用原始内存是错误的,虽然vs2010不报错,但是也不要这样做。
allocTest.construct(p, CTest()); //构造第一个对象,调用对象的构造函数
allocTest.destroy(p); //调用对象的析构函数,一旦元素被销毁,就可以在这块内存上保存其他的指定对象。
allocTest.deallocate(p, ); //释放从p开始的内存,从p开始的位置保存了10个CTest类型的对象。这个10是之前调用allocate时指定的。在调用此函数前,必须对此内存块中已经构造的对象调用destroy(); //16.uninitialized_copy(beg1, end1, beg2)
// uninitialized_copy_n(beg1, n, beg2):从输入迭代器指定的范围拷贝元素到迭代器beg2指定的未构造的原始内存中。此函数返回值为beg2中最后一个被构造的元素的尾后迭代器。
// uninitialized_fill(beg1, end1, t)
// uninitialized_fill_n(beg1, n, t):在由前两个参数指定的序列中,创建对应数目的对象,并用t来进行初始化。
allocator<CTest> allocTest;
CTest *pTest = allocTest.allocate();
vector<CTest> vecTest;
for(int i = ; i < ; ++i) {vecTest.emplace_back(i);}
auto pTem = uninitialized_copy(vecTest.begin(), vecTest.end(), pTest);
uninitialized_fill(pTem, pTem + , );
//pTest指向的内存中对象的值:0到9,10个1 allocator<unique_ptr<int>> allocTest;
auto *pTest = allocTest.allocate();
uninitialized_fill(pTest, pTest + , new int());
int sum = ;
for(int i = ; i < ; ++i){sum += *(pTest[i]);} //sum = 20; //17

 void Fun0(CRITICAL_SECTION* p)
 {
   LeaveCriticalSection(p);
 }

 auto FunTest = [](CRITICAL_SECTION* p){LeaveCriticalSection(p);};
 CRITICAL_SECTION Cs;
 shared_ptr<CRITICAL_SECTION> pShareCs(&Cs, [](CRITICAL_SECTION* p){LeaveCriticalSection(p);});
 unique_ptr<CRITICAL_SECTION, decltype(Fun0)*> pUniqueCs0(&Cs, Fun0);
 unique_ptr<CRITICAL_SECTION, decltype(FunTest)> pUniqueCs1(&Cs, FunTest);
 //unique_ptr<CRITICAL_SECTION, decltype([](CRITICAL_SECTION* p){LeaveCriticalSection(p);})> pUniqueCs2(&Cs, [](CRITICAL_SECTI  ON* p){LeaveCriticalSection(p);});
 //error C3477: lambda 不能出现在未计算的上下文中
 //unique_ptr<CRITICAL_SECTION> pUniqueCs3(&Cs, Fun1);
 //error C2664: “std::unique_ptr<_Ty>::unique_ptr(_RTL_CRITICAL_SECTION *,const std::default_delete<_Ty> &)”: 不能将参数 2 从“`an  onymous-namespace'::<lambda0>”转换为“const std::default_delete<_Ty> &”

 
 

C++Primer 第十二章的更多相关文章

  1. C++ Primer : 第十二章 : 文本查询程序

    C++ Primer书上这个例子讲的很不错,写写帮助自己理解标准库和智能指针. .h 文件内容 #include <fstream> #include <iostream> # ...

  2. C++ Primer : 第十二章 : 动态内存之unique_ptr和weak_ptr

    unique_ptr 一个unique_ptr拥有它所管理的对象,与shared_ptr不同,unique_ptr指向的对象只能有一个用户.当unique_ptr被销毁后,它所指向的对象也被销毁. 定 ...

  3. C++ Primer : 第十二章 : 动态内存之allocator类

    标准库allocator类定义在头文件 <memory>中.它帮助我们将内存分配和构造分离开来,它分配的内存是原始的.未构造的. 类似vector,allocator也是一个模板类,我们在 ...

  4. C++ Primer : 第十二章 : 动态内存之动态数组

    动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...

  5. C++ Primer : 第十二章 : 动态内存之shared_ptr与new的结合使用、智能指针异常

    shared_ptr和new结合使用 一个shared_ptr默认初始化为一个空指针.我们也可以使用new返回的指针来初始化一个shared_ptr: shared_ptr<double> ...

  6. C++ Primer : 第十二章 : 动态内存之动态内存管理(new和delete)

    C++语言定义了两个运算符来分配和释放动态内存:运算符new分配内存,运算符delete释放new分配的内存. 运算符new和delete 使用new动态分配和初始化对象 在自由空间分配的内存是无名的 ...

  7. C++ Primer : 第十二章 : 动态内存之shared_ptr类实例:StrBlob类

    StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存. 定义StrBlob类 ...

  8. C++ Primer : 第十二章 : 动态内存之shared_ptr类

    在C++中,动态内存是的管理是通过一对运算符来完成的:new  ,在动态内存中为对象分配空间并返回一个指向该对象的指针,delete接受一个动态对象的指针,销毁该对象,并释放该对象关联的内存. 动态内 ...

  9. C++ Primer之 十二章 类

    1.关于类的const对象 const对象只能调用声明为const的成员函数,在这篇csdn博客中也讨论了这个问题. 究其原因是因为 const 对象A 调用了非const函数F, F因为没有cons ...

随机推荐

  1. von Neumann architecture

    COMPUTER ORGANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION 3.1 COMPUTER COMPONEN ...

  2. JAVA中的throws和throw的区别

    Java     一直对java中的throws和throw不太理解.最近一直在查这两个方面的资料,算是能明白一点吧.如果我下面的观点哪有不对,希望指出来,我加以改进.         throw:( ...

  3. 低功耗蓝牙4.0BLE编程-nrf51822开发(10)-描述符

    特性中的属性有两种:属性值或描述符. 支持通知或指示的特性中默认有一个描述符:客户端特性配置描述符(Client Characteristic Configuration Descriptor,CCC ...

  4. Difference Search Path

    1.Framework Search Path           where to search frameworks (.framework bundles) in addition to sys ...

  5. the differences between function and procedure

    一.自定义函数: 1. 可以返回表变量 2. 限制颇多,包括 不能使用output参数: 不能用临时表: 函数内部的操作不能影响到外部环境: 不能通过select返回结果集: 不能update,del ...

  6. Java字符串的那些事儿。。。。

    计划围绕以下几个方面 1.内存 2.正则表达式 3.String.format 4.编码 1.内存 先来看个经典的例子 public class Blog { public static void m ...

  7. Oracle数据导入导出imp/exp

    功能:Oracle数据导入导出imp/exp就相当与oracle数据还原与备份. 大多情况都可以用Oracle数据导入导出完成数据的备份和还原(不会造成数据的丢失). Oracle有个好处,虽然你的电 ...

  8. 7Z命令行

    7-Zip (A) 4.57 Copyright (c) 1999-2007 Igor Pavlov 2007-12-06 Usage: 7za <command> [<switch ...

  9. Selenium2学习-026-WebUI自动化实战实例-024-获取页面元素

    非常简单的方法封装,就不啰嗦了,直接上码咯 ^_^ /** * Get element. It will be return null when there is not such element. ...

  10. JS-006-表格元素操作

    直接上菜咯... 以下为 HTML 表格源码: <html> <head> <meta http-equiv="Content-Type" conte ...