C++基础智能指针之垃圾回收

原创 2018年04月16日 21:56:10

  • 问题引入:Java和C#等语言有自己的垃圾回收机制,.net运行时和java虚拟机可以管理分配的堆内存,在市区对象时自动回收,因此我们不需要去考虑垃圾回收问题,但是C++没有垃圾回收机制,我们必须要自己去释放分配的堆内存。

  • 知识点:智能指针是指向动态分配(堆)对象指针,用于生存期控制,能够确保自动正确的销毁动态分配的对象,防止内存泄露。它的一种通用实现技术是使用引用计数。每次使用它,内部的引用计数加1,每次析构一次,内部引用计数减1,减为0时,删除所指向的堆内存。C++中的智能指针包括:
std::shared_ptr
std::unique_ptr
std::weak_ptr
  • 怎么用:

1、智能指针std::shared_ptr的用法:通过构造函数、赋值函数、std::make_shared函数进行初始化,还可以指定删除器。智能指针的原始指针通过get()函数获取。

std::shared_ptr<int >p = (new int(2));
std::shared_ptr<int >p2 = p;
std::shared_ptr<Server> pServer= std::make_shared<Server>();
void DeleteIntPtr(int *p)
{
	delete p;
}
std::shared_ptr<int >p = (new int,DeleteIntPtr);  
std::shared_ptr<char>pBuffer = new char[len];
char* pchar = pBuffer.get();

     注意事项:

        A、不要把一个原生指针给多个智能指针管理:

int* ptr = new int;
shared_ptr<int> p1(ptr);
shared_ptr<int> p2(ptr); //logic error
导致ptr被删除两次

            B、不要把this指针给shared_ptr:

       C要在函数实参里创建shared_ptr ,function ( shared_ptr<int>(new int), g( ) ); 有缺陷可能的过程是先new int,然后调g( ),g( )发生异常,shared_ptr<int>没有创建,int内存泄露shared_ptr<int> p(new int()); f(p, g()); 

       D、shared_ptr作为对象成员时,小心因循环引用而造成无法释放资源。

struct A;
struct B;
struct A
{
std::shared_ptr<B> m_b;
};

struct B
{
std::shared_ptr<A> m_a;
};

std::shared_ptr<A> ptrA(new A);
std::shared_ptr<B> ptrB(new B);
ptrA->m_b = ptrB;
ptrB->m_a = ptrA;

//ptrA和ptrB相互引用,离开作用域时引用计数都为1,导致内存没有被释放,
//解决办法是把A和B任何一个的成员变量改为weak_ptr


struct B
{
std::weak_ptr<A> m_a;
};

//ptrB->m_a不会增加A对象的引用计数,因此A对象离开作用域时,引
//用计数为0,m_b的引用计数减一,b离开作用域后引用计数由1减为0.

    2、弱引用指针weak_ptr是为配合shared_ptr而引入的一种智能指针来协助shared_ptr工作,它可以从一个shared_ptr或另一个weak_ptr对象构造,它的构造和析构不会引起引用计数的增加或减少。没有重载 * 和 -> 但可以使用lock获得一个可用的shared_ptr对象weak_ptr的使用更为复杂一点,它可以指向shared_ptr指针指向的对象内存,却并不拥有该内存,而使用weak_ptr成员lock,则可返回其指向内存的一个share_ptr对象,且在所指对象内存已经无效时,返回指针空值nullptr。

注意:weak_ptr并不拥有资源的所有权,所以不能直接使用资源。可以从一个weak_ptr构造一个shared_ptr以取得共享资源的所有权。

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <map>

void check(std::weak_ptr<int> &wp)
{
    std::shared_ptr<int> sp = wp.lock(); // 转换为shared_ptr<int>
    if (sp != nullptr)
    {
        std::cout << "still: " << *sp << std::endl;
    } 
    else
    {
        std::cout << "still: " << "pointer is invalid" << std::endl;
    }
}


void mytest()
{
    std::shared_ptr<int> sp1(new int(22));
    std::shared_ptr<int> sp2 = sp1;
    std::weak_ptr<int> wp = sp1; // 指向shared_ptr<int>所指对象

    std::cout << "count: " << wp.use_count() << std::endl; // count: 2
    std::cout << *sp1 << std::endl; // 22
    std::cout << *sp2 << std::endl; // 22
    check(wp); // still: 22
    
    sp1.reset();
    std::cout << "count: " << wp.use_count() << std::endl; // count: 1
    std::cout << *sp2 << std::endl; // 22
    check(wp); // still: 22

    sp2.reset();
    std::cout << "count: " << wp.use_count() << std::endl; // count: 0
    check(wp); // still: pointer is invalid

    return;
}

int main()
{
    mytest();

    system("pause");
    return 0;
}
    3、unique_ptr不会共享它的指针。 无法将它复制到另一个unique_ptr, unique_ptr只能移动。 这意味着内存资源的所有权将转移到新的unique_ptr和原始unique_ptr不再拥有它。
int* p = new int;
std::unique_ptr<int> ptr(p);
std::unique_ptr<int> ptr1 = ptr; //不能复制,编译报错

auto ptr2 = std::move(ptr); //转移所有权, 现在ptr那块内存归ptr2所有, ptr成为无效的指针.

    4、用模板实现的智能指针
//智能指针
//	1、复制对象时,副本和原对象都指向同一块存储区域
template<typename T>
class SmartPtr
{
public:
	SmartPtr(const T * ptr)_ptr(ptr)
	{
		if(_ptr)
		{
			_count = new size_t(1);
		}
		else
		{
			_count = new size_t(0);
		}
	}
	
	SmartPtr(const SmartPtr<T>& rhs)
	{
		_count = rhs._count;
		(*_count)++;
		
		_ptr = rhs._ptr;
	}
	//四部曲
	//1、检查自我赋值,2,与过去断绝关系,3,指向新世界,4,返回*this
	
    SmartPtr &operator = (cosnt SmartPtr<T>& rhs)
	{
		if(*this != rhs)
		{
			if((*_count)==0)
			{
				delete _count;
				delete _ptr;
				_count =NULL;
				_ptr =NULL;
			}
			_count = rhs._count;
			++(*_count);
			_ptr=rhs._ptr;
		}
		return *this
	}
	
	T* operator -> ()
	{
		return _ptr;
	}
	T& operator*()
	{
		return *_ptr;
	}
	
	~SmartPtr()
	{
		(*_count)--;
		if(*_count == 0)
		{
			delete _count;
			delete _ptr;
			_count =NULL;
			_ptr =NULL;
		}
		
	}
private:
	T* _ptr;
	size_t* _count;//指向引用计数器的指针
}


                

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wymtqq/article/details/79966285

智能指针实践,C++真不需要垃圾回收

说来也许不能相信,自己之前并没有在软件开发中大规模引入智能指针,担心效率啊,在vector里面塞满了shared_ptr,一旦遍历,想想都心痛。 如果给有10万元素的vector和list中...
  • SalmonRun
  • SalmonRun
  • 2013-01-07 23:20:34
  • 1663

[内存管理]智能指针与内存池的总结

总结: 内存管理是C++程序开发中永恒的话题,因为没有垃圾回收机制,小心谨慎地管理内存等系统资源是每一个C++开发人员都必须面对面的问题。 boost.smart_ptr库提供了数种新型智能指针,...
  • ajioy
  • ajioy
  • 2012-03-21 18:16:53
  • 2329

C++侵入式智能指针的实现

简介在现代C++编程中,智能指针给我们在资源管理上带来了很多好处,这里就不多说了。在工作中,我们常常会用智能指针来管理资源,其中最常用的就是引用计数类智能指针了(shared_ptr)。资源共享型的智...
  • jiange_zh
  • jiange_zh
  • 2016-09-12 13:07:23
  • 1673

C++中智能指针的设计和使用(转)

转载地址:http://blog.csdn.net/hackbuteer1/article/details/7561235          智能指针(smart pointer)是存储指向动态分配...
  • zhiren2011
  • zhiren2011
  • 2015-07-09 21:16:03
  • 261

智能指针的两种实现(引用计数)

在微信上看到一篇“C++引用计数及智能指针的简单实现”的好文章点击打开链接,通俗易懂,激起了敲代码的兴趣,于是用两种方式实现了简单的智能指针(辅助类+SmartPtr类 vs SmartPtr类)。...
  • ZongYinHu
  • ZongYinHu
  • 2016-05-28 22:28:11
  • 954

再论C++之垃圾回收(GC)

本文已经迁移到: http://cpp.winxgui.com/cn:garbage-collection-in-cplusplus使用智能指针(smart pointers) http://w...
  • xushiweizh
  • xushiweizh
  • 2006-11-24 02:04:00
  • 29144

c++侵入式对象计数设计技术

侵入式对象计数的设计原理相对非侵入式的来说: 具有以下优点: 1、一个资源对象无论被多少个侵入式智能指针包含,从始至终只有一个引用计数变量,不需要在每一个使用智能指针对象的地方都new一个计数对象...
  • wallwind
  • wallwind
  • 2015-12-08 20:22:22
  • 3476

Android系统篇之----Android中的智能指针

一、前言今天我们开启Android系统篇的文章了,其实一直想弄,只是之前一直没有太多深入的了解,最近又把这块拿出来好好看了一下,所以想从新梳理一下,来看看Android中的这块知识,首先我们今天来看一...
  • jiangwei0910410003
  • jiangwei0910410003
  • 2016-05-03 17:27:34
  • 10093

模板和智能指针(c++)

  • 2011年07月24日 22:55
  • 500KB
  • 下载

c++学习笔记—动态内存与智能指针浅析

我们的程序使用内存包含以下几种: 静态内存用来保存局部static对象、类static数据成员以及定义在任何函数之外的变量,在使用之前分配,在程序结束时销毁。 栈内存用来保存定义在函数内部的非st...
  • xujian_2014
  • xujian_2014
  • 2015-01-08 15:45:18
  • 813
收藏助手
不良信息举报
您举报文章:C++基础智能指针之垃圾回收
举报原因:
原因补充:

(最多只允许输入30个字)