首先shared_ptr类型是 C++ 标准库中的一个智能指针,是为多个所有者可能必须管理对象在内存中的生命周期的方案设计的。 在您初始化一个 shared_ptr 之后,您可复制它,按值将其传入函数参数,然后将其分配给其他 shared_ptr 实例。 所有实例均指向同一个对象,并共享对一个“控制块”(每当新的 shared_ptr 添加、超出范围或重置时增加和减少引用计数)的访问权限。 当引用计数达到零时,控制块将删除内存资源和自身。说白了就是个模板类,提供了管理模块和data存储模块。而它的生命周期由引用计数决定。
而make_shared模板则是为shared_ptr分配内存空间的。使用make_shared 比用new要高效,因为你不只要分配data内存还要分配控制块的内存。使用make_shared就可以一步到位。
我们在main函数中获取键盘输入的键值,将其加入keymanager类维护的一个vector容器中,再由keymanager提供的线程从vector中取出键值。一般来说vector更适合跟shared_ptr配套使用。应用场景比较简单,就是将生产者和消费者分开,在keymanager中统一处理键值。
编译环境为Ubuntu 14.04
下面看样例:
sharedptr.h
#pragma once
#include
class ckey
{
public:
ckey(char ikey)
{
key = ikey;
printf("Make a new ckey : %c \n",key);
}
~ckey()
{
printf("Release a ckey : %c \n",key);
}
char getKey()
{
return key;
}
private:
char key;
};
sharedptr.cpp
#include
#include
#include
#include "sharedptr.h"
#include
#include
#include
using namespace std;
class ckeyManager
{
public:
ckeyManager()
:m_threadId(0)
{
pthread_mutex_init(&m_lock, NULL);
}
~ckeyManager()
{
}
//往keyvector容器中添加按键值,由容器保存
void AddKeyItem(std::shared_ptr<ckey> keyValue);
//创建处理线程
bool startMangerThread()
{
int err = -1;
err = pthread_create(&m_threadId, NULL,
ckeyManager::threadProc, (void *)this);
if (0 != err) {
printf("pthread_create fail: %s\n",strerror(err));
}
return (0 == err);
}
protected:
pthread_t m_threadId;
pthread_mutex_t m_lock;
unsigned long threadRun();
private:
std::vector<std::shared_ptr<ckey>> m_keyVector;
unsigned long m_exitCode;
static void* threadProc(void *arg)
{
ckeyManager* threadPtr = (ckeyManager *)arg;
threadPtr->m_exitCode = threadPtr->threadRun();
pthread_exit(&(threadPtr->m_exitCode));
return (void *)&threadPtr->m_exitCode;
}
};
void ckeyManager::AddKeyItem(std::shared_ptr<ckey> keyValue)
{
pthread_mutex_lock(&m_lock);
m_keyVector.insert(m_keyVector.begin(),keyValue);
pthread_mutex_unlock(&m_lock);
}
void select_sleep(int i)
{
struct timeval timeout;
timeout.tv_sec = i;
timeout.tv_usec = 0;
select( 0, NULL, NULL, NULL, & timeout );
}
//键值处理线程
unsigned long ckeyManager::threadRun()
{
printf("ckeyManager thread start \n");
while(1)
{
pthread_mutex_lock(&m_lock);
if (m_keyVector.size() > 0)
{
std::shared_ptr<ckey> keyvalue;
keyvalue = m_keyVector.back();
printf("MANAGER get key value : %c \n",keyvalue->getKey());
m_keyVector.pop_back();
//休眠1s后退出
select_sleep(1);
}
pthread_mutex_unlock(&m_lock);
}
}
int main()
{
char ch;
ckeyManager * keymanage = new ckeyManager();
if(!keymanage->startMangerThread())
{
printf("fail to start thread .\n");
}
system("stty -icanon"); //无缓冲模式,不用按enter就可以直接返回键值
while(1)
{
ch = getchar();
keymanage->AddKeyItem(std::make_shared<ckey>(ch));
}
return 0;
}
编译指令: g++ -std=c++11 -o ptr sharedptr.cpp -lpthread
要使用c++11
我们可以看到当在线程处理完成后由于引用为0调用了ckey类的析构函数 Release a ckey 。
这个例子其实能比较好的反应在实际开发中我们比较常用的一种应用模式。而不是像其他网上查找到的例子都是在一个main函数中就做完了所有事情。只在main函数中运行的话那相当于是整个应用的生命周期都完结了,这不能体现shared_ptr这个智能指针的优势。例子中很好的体现了在处理线程中shared_ptr管理的对象引用计数为0时确实调用了析构函数释放了该段内存。
有什么不明白的地方可以在下方评论,如果觉得有用可以点赞~ 谢谢。