shared_ptr 与 make_shared  初识

shared_ptr 与 make_shared 初识

#define _ALLOCATE_MAKE_SHARED( \
	TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, X1, X2, X3, X4) \
template<class _Ty COMMA LIST(_CLASS_TYPE)> inline \
	shared_ptr<_Ty> make_shared(LIST(_TYPE_REFREF_ARG)) \
	{	/* make a shared_ptr */ \
	_Ref_count_obj<_Ty> *_Rx = \
		new _Ref_count_obj<_Ty>(LIST(_FORWARD_ARG)); \
	shared_ptr<_Ty> _Ret; \
	_Ret._Resetp0(_Rx->_Getptr(), _Rx); \
	return (_Ret); \
	} \

C++11:

shared_ptr:智能指针共享型

make_shared是一个模板函数,std::make_shared  以上是源码。

使用示例:

class A{

public:

A(int a_):a(a_);

~A();

private:

    int a;

}


shared_ptr<A> obj_a = make_shared<A>(3);

make_shared在动态内存中申请一块A类对象内存 并初始化这个对象。然后返回一个shared_ptr智能指针指向这个对象,由shared_ptr管理动态内存

make_shared构造对象的时候最多带10个参数


shared_ptr  记录引用内存对象做一个计数(复制,拷贝等计数+1),当智能指针析构时计数-1 计数为0时没有指针指向这一段内存,此时释放这段内存。

  1. 构造函数

    1. shared_ptr<T> sp;空的shared_ptr,可以指向T类型的对象 引用计数 = 0

    2. shared_ptr<T> sp(new T());shared_ptr指向T类型的对象  引用计数=1

    3. shared_ptr<T> sp(p1) ;   sp与p1 共同管控同一段内存  引用计数=2

    4. shared_ptr<T[]> sp;C++17之后支持

    5. shared_ptr<T[]> sp(new T[5]{});  C++17之后支持

    6. shared_ptr<T> sp(NULL,D());  C++17之后支持 利用仿函数,释放前调用。

    7. shared_ptr<T> sp(new T(),D())   C++17之后支持 利用仿函数,释放前调用。

  2. =  赋值

    1. shared_ptr<T> p1(new T(1));  shared_ptr<T> p2(new T(2));   p1 = p2;  T(1) 的引用计数-1,被释放   T(2)的引用计数=2

    2. p1 = NULL   主动释放计数-1  被释放

  3. reset

    1. p1.reset();  重置智能指针,所有的引用计数-1

    2. p1.reset(new T(7));  原有的引用计数-1,重置智能指针,指向新的T(7)

    3. p1.reset(p1,D());  指定删除器

  4. swap;  交换


shared_ptr  交叉引用导致内存泄漏 可以使用weak_ptr配合使用,不会引起计数+1 -1 ; 允许共享指针赋值给weak_ptr,不支持 * 和 ->的使用;

 如果要使用weak_ptr可以使用 .lock()提升为共享指针去构造一个新的shared_ptr执行 *和 ->的操作

dynamic_pointer_cast:

class A{

//.....

}


class B:public A{

//...

}


void func(const shared_ptr<A>& a_test ){

    auto msg = std::dynamic_pointer_cast<B>(a_test);   //a_test拥有  B 类对象的所有资源

}

A * a_p = new B();

shared_ptr<A> p(a_p );

func(p);


排查性的独享智能指针

unique_ptr取代了  auto_ptr

不允许 p1=p2赋值操作 ; 不允许  unique_ptr<string> p3(p4) 复制构造;但是可以  p1 = std::move(p2) 将p2管理的一段内存交给p1,p2此时被清除置空

  1. 依旧不能两个智能指针指向同一段内存

  2. 使用容器管理是安全的(禁止了  = 操作)

  3. unique_ptr构造:

    1. unique_ptr<T> up; 空的unique_ptr,可以指向T类型的对象

    2. unique_ptr<T> up(new T());unique_ptr,指向T类型的对象,或者  up = std::move(p1)

    3. unique_ptr<T[]> up; 

    4. unique_ptr<T[]> up(new T[5]);  在up对象被释放的时候  会调用5次delete[] T  析构   ;auto_ptr 不可以

    5. unique_ptr<T,DestructFunc>up(); 利用仿函数,释放前调用。

      1. struct DestructFunc{

        void operator()(T *p){

            p->func();

            delete p;

        }

        }

  4. unique_ptr<T> up(new T());  可以主动释放  up = NULL;  


C++98 :

auto_ptr智能指针,利用智能指针对象在失效的时候自动释放,去delete 绑定的指针对象

注意  1.不要定义为全局的:全局的对象要在程序结束才会释放,那就是去了智能的意义了。

        2.不要定义为智能指针 为指针。同样多出了一个指针,智能指针也失去意义了

        不要将一个智能指针赋值给一个同类型的智能指针对象,除非你真正知道带来的后果是什么

            auto_ptr<string> p1( new string("aaaaaa"));

            auto_ptr<string> p1(new string("bbbbbbbbb"));

            p1 = p2;

            reset():清空原有管理的,重新设置一个新的

            release():交出当前管理的,清空

            p1内部的指针会被释放(reset()),p2会交出(release())自己管理的内存,交给p1管理

        

        auto_ptr陷阱  不能把同一段内存交给多个智能指针管理:如果其中一个已经被释放,当时用另外一个的时候就会崩溃

        如果智能指针被放进了vector<auto_ptr<string>> A   ,当执行 A[0] = A[1]  A[1]内部管理的内存被释放,直接崩溃