CppPrimer笔记 Chapter12 动态内存
标签: Cpp
动态内存与智能指针(12.1)
shared_ptr
允许多个指针指向同一个对象
指向shared_ptr
所管理的对象- 智能指针可以认为是能记录有多少个指向相同对象,因而能在恰当时调用析构函数自动释放
- 使用动态内存的三种原因
- 程序不知道自己需要使用多少对象(动态数组)
- 程序不知道所需对象的准确类型(第15章)
- 程序需要在多个对象间共享数据(通过类成员取值
shared_ptr
来构建一个可以共享的,会自动销毁的对象)
- delete一个指针后,指针值变为无效.但仍保存了已经释放了的动态内存的地址.为
悬空指针
- delete一个动态分类的对象的指针时将执行析构函数
- 接受指针参数的智能指针构造函数是
explicit
(禁止隐式类型转换)因而
shared_ptr<int> p1 = new int(1024);//error
shared_ptr<int> p2(new int(1024)); //ok
shared_ptr<int>clone(int p){
return new int(p);} //error
shared_ptr<int>clone(int p){
return shared_ptr<int>(new int(p));} //ok
- 不要混合使用普通指针与智能指针,也不好使用
get
初始化另一个智能指针,或为智能指针赋值
void process(shared_ptr<int> ptr){}
int *x(new int(1024));
process(x);//error int*不能转化为shared_ptr<int>
process(shared_ptr<int>(x));
int j = *x;//未定义:x在process中被释放了
shared_ptr<int> p(new int(42));
int *q = p.get();
{shared_ptr<int> g(q);}//new block end,g释放了p的对象
int foo = *p;//未定义 使用悬空指针
- 发生异常时,直接管理的内存是不会被自动释放的
shared_ptr<connection>p(&c,end_connection);
会调用end_connection来进行销毁,这时c 不是由new分配的内存 也务必调用删除器而不是默认的delete
unique_ptr
独占所指向的对象,
构建时需要绑定到一个new返回的指针上,同样只能采用直接初始化.
由于为独占,不支持拷贝操作,
但可以用release()
或reset
将(非const unique_ptr)指针的所有权进行转移.注意release()
放弃指针时造成的指针丢失
release()
对于指针类型,会销毁管理的指针(调用delete[])unique_ptr<objT,delT>p(new objT,fcn)
其调用自定义删除函数类似关联容器
而与shared_ptr
有区别weak_ptr
为弱引用,将weak_ptr
绑定到一个shared_ptr
,
但不会改变shared_ptr
的引用计数,因而可能会不存在,要利用lock
来访问
动态数组(12.2)
allocator
为了使得内存分配与对象初始化分离.进而可以没有默认构造函数也可以动态分配内存- 使用
allocator
allocator<string> alloc;
int n = 10;
auto const base = alloc.allocate(n);
auto q = base;
alloc.construct(q++);
alloc.construct(q++,10,'c');
alloc.construct(q++,"hi");
cout<<*p<<endl;
while(q != p)alloc.destroy(--q);
alloc.deallocate(p,n);
vector<int> vec{ 1, 2, 3, 4, 5 };
allocator<int>alloc;
auto const base = alloc.allocate(vec.size()*2);
auto q = uninitialized_copy(vec.begin(), vec.end(), base);
q = uninitialized_fill_n(q, vec.size(), 42);
//注意 打印为倒序,42 42 42 42 42 5 4 3 2 1
while (q != base){ cout << *(--q) << endl; }