12.1动态内存与智能指针
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了12.1动态内存与智能指针相关的知识,希望对你有一定的参考价值。
1.shared_ptr<>:允许多个指针指向同一个对象 初始化方式: shared_ptr<int> p1 = make_shared<int>(10);//最好使用这种方式 shared_ptr<int> p2(new int(20)); //只能用直接初始化方式 和普通指针有一样的操作,*,->,swap等 支持拷贝与赋值与自定义删除器,特别地: p.get()能返回p中保存的指针,如果指针指针释放了其对象,返回指针所指的对象也就消失了。 p.use_count()返回与p共享的只能指针数量,比较慢,主要用来调试。 p.unique()若p.use_count()为1,返回true,否则返回false。 shared_ptr会自动销毁所管理的对象并且会自动释放相关联的内存。 原因是因为内存采用了:引用计数。 当计数为0就会自动释放。 p1 = p2; //p2引用计数加1,p1引用计数减1 不能将一个内置指针隐式转化为指针指针 shared_ptr<int> f(int p) { return shared_ptr<int>(new int(p));//不能直接放回new int(p) } shared_ptr<T> p(q); //p管理内置指针q所指的对象,q必须指向new分配的内存,且能够转换为T*类型 shared_ptr<T> p(u); //p从unique_ptr u接管对象的所有权,将u置为空 shared_ptr<T> p(q, d); //q为内置指针,d为可调用对象作为删除器 shared_ptr<T> p(p2, d);//p是shared_ptr2的拷贝,p使用对象d作为删除器 p.reset(); //释放p,将p置为空 p.reset(q); //p会指向q p.reset(q, d); //调用删除器d shared_ptr不支持管理动态数组,当初始化动态数组时必须定义自己的删除器: shared_ptr<int> p(new int[10], [](int *n){ delete[]n; });//必须要自定义删除器 因此访问数组中的元素操作也会不同: for(int i = 0; i < 10; ++i) { *(p.get() + i) = u(e);//只能通过get()来访问 } 注意:不要用get初始化另一个智能指针或者为另一个智能指针赋值 2.unique_ptr<>:独占所指向的对象,也就是同一时刻只能有一个unique_ptr指向一个给定的对象 初始化形式: unique_ptr<int> p(new int(10)); //只能直接初始化 不支持拷贝与赋值 支持自定义删除器,和普通指针也有*,->,swap等,也有get()函数 unique_ptr<T> u1; //指向类型为T的对象,会使用delete unique_ptr<T, D> u2; //会使用删除器D来释放 unique_ptr<T, D> u(d);//空unique_ptr,使用d来代替delete u = nullptr; //释放u所指的对象,将u置为空 u.release(); //u放弃对指针的控制权,返回指针,将u置为空 u.reset(); //释放u所指的对象 u.reset(q); //如果提供内置指针q,令u指向这个对象 u.reset(nullptr); unique_ptr能够管理动态数组: unique_ptr<int[]> a; unique_ptr<int[]> a(new int[10]); //注意类型 能够使用u[i]访问数组 其他操作和普通一样 3.weak_ptr<>:不控制所指向对象生存期的只能指针,指向由一个shared_ptr管理的对象 初始化形式: weak_ptr<int> w; //p必须为shared_ptr weak_ptr<int> w = p; weak_ptr<int> w(p); w = p; w.reset() //将w置为空 w.use_count(); //与w共享对象的shared_ptr数量 w.expired(); //若w.use_count()为0,返回true,否则返回false w.lock(); //如果expired为true,返回一个空shared_ptr,否则返回一个指向w的对象的shared_ptr 注意:由于对象可能不存在,不能直接访问对象,需要使用lock weak_ptr有一个非常有用的地方在于,破除shared_ptr的循环引用: class A { public: A(int a) : i(a) {} ... public: int i; shared_ptr<int> p; }; int main() { shared_ptr<A> one = make_shared<A>(1); shared_ptr<A> two = make_shared<A>(2); one->p = two; two->p = one; return 0; } 这种情况造成了循环引用,作用域结束时one和two都不会被释放,正确的做法是将one和two其中一个变为weak_ptr class A; class B; class A { private: shared_ptr<B> p; }; class B { private: shared_ptr<A> p; }; 这种情况也造成了循环引用,应该讲其中一个变为weak_ptr
以上是关于12.1动态内存与智能指针的主要内容,如果未能解决你的问题,请参考以下文章