C++Primer 第十二章
//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 第十二章的更多相关文章
- C++ Primer : 第十二章 : 文本查询程序
C++ Primer书上这个例子讲的很不错,写写帮助自己理解标准库和智能指针. .h 文件内容 #include <fstream> #include <iostream> # ...
- C++ Primer : 第十二章 : 动态内存之unique_ptr和weak_ptr
unique_ptr 一个unique_ptr拥有它所管理的对象,与shared_ptr不同,unique_ptr指向的对象只能有一个用户.当unique_ptr被销毁后,它所指向的对象也被销毁. 定 ...
- C++ Primer : 第十二章 : 动态内存之allocator类
标准库allocator类定义在头文件 <memory>中.它帮助我们将内存分配和构造分离开来,它分配的内存是原始的.未构造的. 类似vector,allocator也是一个模板类,我们在 ...
- C++ Primer : 第十二章 : 动态内存之动态数组
动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...
- C++ Primer : 第十二章 : 动态内存之shared_ptr与new的结合使用、智能指针异常
shared_ptr和new结合使用 一个shared_ptr默认初始化为一个空指针.我们也可以使用new返回的指针来初始化一个shared_ptr: shared_ptr<double> ...
- C++ Primer : 第十二章 : 动态内存之动态内存管理(new和delete)
C++语言定义了两个运算符来分配和释放动态内存:运算符new分配内存,运算符delete释放new分配的内存. 运算符new和delete 使用new动态分配和初始化对象 在自由空间分配的内存是无名的 ...
- C++ Primer : 第十二章 : 动态内存之shared_ptr类实例:StrBlob类
StrBlob是一个管理string的类,借助标准库容器vector,以及动态内存管理类shared_ptr,我们将vector保存在动态内存里,这样就能在多个对象之间共享内存. 定义StrBlob类 ...
- C++ Primer : 第十二章 : 动态内存之shared_ptr类
在C++中,动态内存是的管理是通过一对运算符来完成的:new ,在动态内存中为对象分配空间并返回一个指向该对象的指针,delete接受一个动态对象的指针,销毁该对象,并释放该对象关联的内存. 动态内 ...
- C++ Primer之 十二章 类
1.关于类的const对象 const对象只能调用声明为const的成员函数,在这篇csdn博客中也讨论了这个问题. 究其原因是因为 const 对象A 调用了非const函数F, F因为没有cons ...
随机推荐
- memcached学习笔记4--memcache扩展操作memcached
1. 安装并配置memcache扩展库 找到php.ini文件 添加: extendsion= php_memcache.dll 并把对应的dll文件拷贝到ext目录 2. 使用PHP对Memcahc ...
- Linux命令echo -e
在Linux命令中 echo -e 这个参数e是什么意思. echo –e “I will use ‘touch’ command to create 3 files.” 这里参数e的作用是什么 ma ...
- 在Delphi下,如何使ShowMessage中的按钮中文化
如果你使用messagedlg(对showmessage也适用)可以汉化定义按钮caption的常量,具体操作步骤如下: 1. 打开文件consts.pas(在Delphi安装目录的/source ...
- 在Delphi下基于MapWinGIS添加和删除图层标注的方法
unit Form_MainU; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, ...
- Sql Server建立链接服务器访问Access的MDB数据库
EXEC master.dbo.sp_addlinkedserver @server = N'test', @srvproduct=N'OLE DB Provider for Jet', @provi ...
- nrf51822裸机教程-SPI(主)
关于SPI总线的介绍这里就不细说了,网上有很多介绍SPI总线时序的. SPI总线的本质就是一个环形总线结构,在时钟驱动下两个双向移位寄存器进行数据交换. 所以SPI总线的特色就是:传输一字节数据的同时 ...
- BLE-NRF51822-实现简单扫描器
在sdk目录 XXX:\Keil_v5\ARM\Pack\NordicSemiconductor\nRF_Examples\9.0.0\ble_central 下有官方提供的主从连接的demo. 官 ...
- oj 1031 random permutation
Problem A: Random Permutations Time Limit: 1 Sec Memory Limit: 128 MB Submit: 91 Solved: 54 Descri ...
- HBase协处理器统计表数据量
1.Java代码实现 import org.apache.hadoop.hbase.client.coprocessor.AggregationClient; import org.apache.ha ...
- Windows下MinGW编译Qt4
还真不是吹,这个问题折磨我一天……前些天转载了一篇关于<Eclipse+Qt开发环境设置>和<Eclipse+MinGW+Qt开发环境设置>两片文章,里面讲述了QT的开源版本q ...