shared_ptr原理和使用

一、原理

为了避免new了对象后忘记delete,或者对象的销毁时机不确定,通过shared_ptr可以自动销毁没有被引用的对象。

二、注意点

shared_ptr并不能解决循环引用的问题,如果有循环引用,不能自动delete指向的对象。
shared_ptr 线程不安全

三、测试

#pragma once
#include <memory>
#include <iostream>
using namespace std;
class SharedPtrClass
{
public:
	
	int a;
	bool sharedPtr;
	shared_ptr<SharedPtrClass> t;
	SharedPtrClass(bool sharedPtr)
	{
		this->sharedPtr = sharedPtr;
		cout << "SharePrtClass new" << (sharedPtr?" sharedPtr":" class")<< endl;
	}
	~SharedPtrClass()
	{
		cout << "SharePtrClass free " << (sharedPtr?" sharedPtr":" class") << endl;
	}
};
class SharedPtr
{
public:

	void doTest()
	{
		cout << "autoDelete before" << endl << endl;
		autoDelete();
		cout << "autoDelete exit" << endl << endl;

		cout << endl << endl << endl;

		cout << "circularRef before" << endl << endl;
		circularRef();
		cout << "circularRef exit" << endl << endl;
		

	}
	void autoDelete()
	{
		cout << "autoDelete class start1" << endl;

		SharedPtrClass* a = new SharedPtrClass(false); //没有主动delete,函数退出时,并不会a指向的对象,导致内存泄漏
		cout << "autoDelete class end1" << endl;
		cout << endl;

		cout << "autoDelete shared_ptr start2" << endl;
		shared_ptr<SharedPtrClass> b(new SharedPtrClass(true)); //智能指针在函数退出时,计数变0,从而析构指向的对象
		cout << "autoDelete shared_ptr end2" << endl;
		cout << endl;
	
	}
	void circularRef()
	{
		cout << "circularRef start1" << endl;
		shared_ptr<SharedPtrClass> a(new SharedPtrClass(true));
		shared_ptr<SharedPtrClass> b(new SharedPtrClass(true));
		a->t = b;
		b->t = a;//循环引用,不能自动delete,导致内存泄漏,如果去掉这行,两个对象都能delete
		cout << "circularRef end1" << endl;
		cout << endl;

	}
	
};

四、输出

autoDelete before

autoDelete class start1
SharePrtClass new class
autoDelete class end1

autoDelete shared_ptr start2
SharePrtClass new sharedPtr
autoDelete shared_ptr end2

SharePtrClass free sharedPtr
autoDelete exit

circularRef before

circularRef start1
SharePrtClass new sharedPtr
SharePrtClass new sharedPtr
circularRef end1

circularRef exit

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
智能指针 智能指针shared_ptr的⽤法 的⽤法   为了解决C++内存泄漏的问题,C++11引⼊了智能指针(Smart Pointer)。   智能指针的原理是,接受⼀个申请好的内存地址,构造⼀个保存在栈上的智能指针对象,当程序退出栈的作⽤域范围后,由于栈上的变 量⾃动被销毁,智能指针内部保存的内存也就被释放掉了(除⾮将智能指针保存起来)。   C++11提供了三种智能指针:std::shared_ptr, std::unique_ptr, std::weak_ptr,使⽤时需添加头⽂件<memory>。   shared_ptr使⽤引⽤计数,每⼀个shared_ptr的拷贝都指向相同的内存。每使⽤他⼀次,内部的引⽤计数加1,每析构⼀次,内部的引⽤ 计数减1,减为0时,删除所指向的堆内存。shared_ptr内部的引⽤计数是安全的,但是对象的读取需要加锁。 1. shared_ptr的基本⽤法 初始化   可以通过构造函数、std::make_shared<T>辅助函数和reset⽅法来初始化shared_ptr: #include "stdafx.h" #include <iostream> #include <future> #include <thread> using namespace std; class Person { public: Person(int v) { value = v; std::cout << "Cons" <<value<< std::endl; } ~Person() { std::cout << "Des" <<value<< std::endl; } int value; }; int main() { std::shared_ptr<Person> p1(new Person(1));// Person(1)的引⽤计数为1 std::shared_ptr<Person> p2 = std::make_shared<Person>(2); p1.reset(new Person(3));// ⾸先⽣成新对象,然后引⽤计数减1,引⽤计数为0,故析构Person(1) // 最后将新对象的指针交给智能指针 std::shared_ptr<Person> p3 = p1;//现在p1和p3同时指向Person(3),Person(3)的引⽤计数为2 p1.reset();//Person(3)的引⽤计数为1 p3.reset();//Person(3)的引⽤计数为0,析构Person(3) return 0; }   注意,不能将⼀个原始指针直接赋值给⼀个智能指针,如下所⽰,原因是⼀个是类,⼀个是指针。 std::shared_ptr<int> p4 = new int(1);// error   reset()包含两个操作。当智能指针中有值的时候,调⽤reset()会使引⽤计数减1.当调⽤reset(new xxx())重新赋值时,智能指针⾸先是⽣ 成新对象,然后将就对象的引⽤计数减1(当然,如果发现引⽤计数为0时,则析构旧对象),然后将新对象的指针交给智能指针保管。 获取原始指针   std::shared_ptr<int> p4(new int(5)); int *pInt = p4.get(); 指定删除器   智能指针可以指定删除器,当智能指针的引⽤计数为0时,⾃动调⽤指定的删除器来释放内存。std::shared_ptr可以指定删除器的⼀个原 因是其默认删除器不⽀持数组对象,这⼀点需要注意。   2. 使⽤shared_ptr需要注意的问题   但凡⼀些⾼级的⽤法,使⽤时都有不少陷阱。 不要⽤⼀个原始指针初始化多个shared_ptr,原因在于,会造成⼆次销毁,如下所⽰: int *p5 = new int; std::shared_ptr<int> p6(p5); std::shared_ptr<int> p7(p5);// logic error 不要在函数实参中创建shared_ptr。因为C++的函数参数的计算顺序在不同的编译器下是不同的。正确的做法是先创建好,然后再传 ⼊。 function(shared_ptr<int>(new int), g()); 禁⽌通过shared_from_this()返回this指针,这样做可能也会造成⼆次析构。 避免循环引⽤。智能指针最⼤的⼀个陷阱是循环引⽤,循环引⽤会导致内存泄漏。解决⽅法是AStruct或BStruct改为weak_ptr。 struct AStruct; struct BStruct; struct AStruct { std::shared_ptr<BStruct> bPtr; ~AStruct() {

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值