C++11引用了智能指针来解决内存泄漏的问题,特别在大型项目中new和delete频繁使用后,导致后期维护成本的持续走高。智能指针可以很好解决这一问题,但智能指针的使用也存在一些陷阱,只有熟练使用之后才能让它成为利器。为了更好地反应问题现象,先封装一个检测内存泄漏的API来进行测试,下面就shared_ptr,unique_ptr,weak_ptr进行说明。
- 内存检测api
#ifndef _MEMORYLEAKCHECK_H__
#define _MEMORYLEAKCHECK_H__
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#include <assert.h>
#ifdef _DEBUG
# define new DEBUG_CLIENTBLOCK
#endif
#ifdef _DEBUG
# define DEBUG_CLIENTBLOCK new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
# define DEBUG_CLIENTBLOCK
#endif
void ExitCheckout()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
assert(_CrtDumpMemoryLeaks() == 0);
}
#endif /*_MEMORYLEAKCHECK_H__*/
- 测试类
smart.h
#ifndef _SMART_H__
#define _SMART_H__
#include <memory>
typedef struct
{
int iFrameHeader;
short sDataLen;
char acData[1];
int iFrameTail;
}ST_DATA, *PST_DATA;
class CSmart;
typedef std::weak_ptr<CSmart> CSmartW;
typedef std::unique_ptr<CSmart> CSmartU;
typedef std::shared_ptr<CSmart> CSmartS;
class CSmart : public std::enable_shared_from_this<CSmart>
{
public:
int m_iTest;
public:
void Print();
void Set(int iData);
CSmartS GetObject();
std::shared_ptr<char> GetSharedFrame(int iDataLen);
std::unique_ptr<char[]> GetUniqueFrame(int iDataLen);
void SetsharedFrame(std::shared_ptr<char> pcData);
void SetUniqueFrame(std::unique_ptr<char[]>& pcData);
public:
CSmart();
~CSmart();
//CSmart(const CSmart&) = delete;
//CSmart& operator = (const CSmart&) = delete;
//~CSmart() = default;
};
//============================================================
class CBaseB;
class CBaseA
{
public:
std::weak_ptr<CBaseB> m_pobjBaseB;
//std::shared_ptr<CBaseB> m_pobjBaseB;
public:
void Print() { printf("CBaseA\n"); }
public:
CBaseA() = default;
~CBaseA() { printf("~CBaseA\n"); }
};
class CBaseB
{
public:
std::weak_ptr<CBaseA> m_pobjBaseA;
//std::shared_ptr<CBaseA> m_pobjBaseA;
public:
void Print() { printf("CBaseB\n"); }
public:
CBaseB() = default;
~CBaseB() = default;
};
#endif /*_SMART_H__*/
smart.cpp
#include "stdafx.h"
#include "smart.h"
CSmart::CSmart():m_iTest(0)
{
}
CSmart::~CSmart()
{
printf("~CSmart\n");
}
void CSmart::Print()
{
printf("function:test\n");
}
void CSmart::Set(int iData)
{
m_iTest = iData;
printf("set value:%d\n", m_iTest);
}
CSmartS CSmart::GetObject()
{
//return (CSmartS)this;
return shared_from_this();
}
std::shared_ptr<char> CSmart::GetSharedFrame(int iDataLen)
{
std::shared_ptr<char> pstChar(new char[sizeof (ST_DATA)+iDataLen - 1](), std::default_delete<char[]>());
PST_DATA pstData = (PST_DATA)(pstChar.get());
pstData->iFrameHeader = 0xFF;
pstData->sDataLen = iDataLen;
pstData->iFrameTail = 0xAA;
return pstChar;
}
std::unique_ptr<char[]> CSmart::GetUniqueFrame(int iDataLen)
{
std::unique_ptr<char[]> pstChar(new char[sizeof (ST_DATA) + iDataLen - 1]());
PST_DATA pstData = (PST_DATA)(pstChar.get());
pstData->iFrameHeader = 0xFF;
pstData->sDataLen = iDataLen;
pstData->iFrameTail = 0xAA;
return pstChar;
}
void CSmart::SetsharedFrame(std::shared_ptr<char> pcData)
{
if (nullptr != pcData.get())
{
PST_DATA pstData = (PST_DATA)(pcData.get());
pstData->iFrameHeader =