【C++】POCO学习总结(十四):引用计数、共享指针、缓冲区管理

【C++】郭老二博文之:C++目录

1、Poco::AutoPtr 智能指针

1.1 说明

Poco::AutoPtr是一个含有引用计数的“智能”指针模版。
Poco::AutoPtr用于支持引用计数的类实例化。支持引用计数的类需要有以下要求:

  • 维护一个引用计数(在创建时初始化为1)
  • 实现void duplicate()方法,增加引用计数
  • 实现void release()方法,减少引用计数,当它达到零时,删除对象

Poco::AutoPtr支持完整的值语义(默认构造函数、复制构造函数、赋值),可以在集合中使用
(例如std::vector或std::map)。
使用Poco::AutoPtr::isNull()或Poco::AutoPtr::operator !()来测试是否为空
AutoPtr强制转换总是类型安全的(内部使用了dynamic_cast,因此无效的强制转换将导致空指针)。

AutoPtr::AutoPtr(C* pObject, bool shared); // shared=true,表示为共享指针

1.2 用法

下面的示例中 RCO 维护一个引用计数_rc,在创建时,将_rc赋值为1,然后实现两个方法duplicate和release,示例源码如下:

#include "Poco/AutoPtr.h"
using Poco::AutoPtr;
class RCO
{
public:
	RCO(): _rc(1){}
	void duplicate()
	{
		++_rc; // Warning: not thread safe!
	}
	void release()
	{
		if (--_rc == 0) delete this; // Warning: not thread safe!
	}
private:
	int _rc;
};

int main(int argc, char** argv)
{
	RCO* pNew = new RCO; // _rc == 1
	AutoPtr<RCO> p1(pNew); // _rc == 1
	AutoPtr<RCO> p2(p1); // _rc == 2
	AutoPtr<RCO> p3(pNew, true); // _rc == 3
	p2 = 0; // _rc == 2
	p3 = 0; // _rc == 1
	RCO* pRCO = p1; // _rc == 1
	p1 = 0; // _rc == 0 -> deleted
	// pRCO and pNew now invalid!
	p1 = new RCO; // _rc == 1
	return 0;
} // _rc == 0 -> deleted

2、Poco::RefCountedObject 引用计数对象

2.1 说明

Poco::RefCountedObject 实现线程安全的引用计数语义。从poco-1.3.4版本开始,它使用特定于平台的原子操作。

Poco::RefCountedObject可以用作实现引用计数的类的基类。
Poco::RefCountedObject有一个受保护的析构函数,禁止复制构造和赋值。
所有引用计数的对象都应该有一个受保护的析构函数,以禁止显式使用delete。

2.2 用法

#include "Poco/RefCountedObject.h"
#include "Poco/AutoPtr.h"
#include <iostream>
using Poco::RefCountedObject;
using Poco::AutoPtr;
class RCO: public RefCountedObject
{
public:
	RCO(){}
	void greet() const
	{
		std::cout << "Hello, world!" << std::endl;
	}
protected:
	~RCO(){}
};

int main(int argc, char** argv)
{
	AutoPtr<RCO> pRCO(new RCO);
	pRCO->greet(); // AutoPtr has -> operator
	(*pRCO).greet(); // AutoPtr has * operator
	std::cout << "refcount: " << pRCO->referenceCount() << std::endl;
	RCO* p1 = pRCO; // AutoPtr supports conversion to plain pointer
	RCO* p2 = pRCO.get();
	return 0;
}

3、Poco::AutoReleasePool 自动释放池

3.1 说明

Poco::AutoReleasePool获取添加到它的每个对象的所有权
当Poco::AutoReleasePool被销毁(或者它的release()方法被调用)时,它通过调用每个对象的release()方法释放对它持有的所有对象的引用。

3.2 用法

#include "Poco/AutoReleasePool.h"
using Poco::AutoReleasePool;
class C
{
public:
	C(){}
	void release() {delete this;}
};

int main(int argc, char** argv)
{
	AutoReleasePool<C> pool;
	C* pC = new C;
	pool.add(pC);
	pC = new C;
	pool.add(pC);
	return 0;
}

// 两次new的C,都将被销毁

4、Poco::SharedPtr 共享指针

4.1 说明

Poco::AutoPtr用于类自身含有引用计数的对象;
Poco::SharedPtr为普通类实现引用计数(自身不需要实现引用计数的类)
头文件:#include “Poco/SharedPtr.h”

警告:将同一个普通指针分配给不同的Poco::SharedPtr将导致该对象有多个所有者,从而导致未定义的行为(换句话说,崩溃)。
一旦对一个对象使用了Poco::SharedPtr,就不要再使用指向那个对象的普通指针了

Poco::SharedPtr支持完整的值语义(默认构造函数、复制构造函数、赋值),并可用于集合(例如std::vector或std::map)。

使用SharedPtr::isNull()或SharedPtr::operator !()来测试是否为空

4.2 用法

#include "Poco/SharedPtr.h"
#include <string>
#include <iostream>
using Poco::SharedPtr;
int main(int argc, char** argv)
{
	std::string* pString = new std::string("hello, world!");
	Poco::SharedPtr<std::string> p1(pString); // rc == 1
	Poco::SharedPtr<std::string> p2(p1); // rc == 2
	p2 = 0; // rc == 1
	// p2 = pString; // 崩溃: 多个所有者
	p2 = p1; // rc == 2
	std::string::size_type len = p1->length(); // 使用“->”解引用
	std::cout << *p1 << std::endl; // 使用“*”解引用 
	return 0;
}

4.3 自定义释放策略

Poco::SharedPtr的默认实现将简单地调用delete pObj
用new[]创建的对象,默认使用delete 肯定会出错,因为释放时,需要调用delete[] pObj

可以在创建Poco::SharedPtr时,使用自定义释放策略

模版如下:

Poco::SharedPtr<T, ReferenceCounter, ArrayReleasePolicy>

使用示例

template <class C>
class ArrayReleasePolicy
{
public:
 static void release(C* pObj) {delete [] pObj;}
};

char* pStr = new char[100];
Poco::SharedPtr<char, Poco::ReferenceCounter, ArrayReleasePolicy> p(pStr);

5、Poco::DynamicFactory 动态工厂类模板

5.1 说明

Poco::DynamicFactory支持按“name”名称创建对象。
头文件:#include “Poco/DynamicFactory.h”
Poco::DynamicFactory管理的所有类必须有一个共同的基类。
Poco::DynamicFactory为基类实例化。
C* Poco::DynamicFactory::createInstance(const std::string& name) const;创建具有给定名称的子类的实例。
要做到这一点,类和它们的实例化器(工厂类)必须在Poco::DynamicFactory中注册

5.2 用法

#include "Poco/DynamicFactory.h"
#include "Poco/SharedPtr.h"
using Poco::DynamicFactory;
using Poco::SharedPtr;

class Base {};
class A: public Base{};
class B: public Base{};

int main(int argc, char** argv)
{
	DynamicFactory<Base> factory;
	# a)注册
	factory.registerClass<A>("A");
	factory.registerClass<B>("B");
	# b)使用工厂来创建
	SharedPtr<Base> pA = factory.createInstance("A");
	SharedPtr<Base> pB = factory.createInstance("B");
	# c)取消注册
	factory.unregisterClass("B");
	# d)检查是否存在
	bool haveA = factory.isClass("A"); // true
	bool haveB = factory.isClass("B"); // false (已取消注册)
	bool haveC = factory.isClass("C"); // false (没有注册过)
	return 0;
}

6、Poco::Instantiator 实例化辅助类

6.1 说明

使用Poco::DynamicFactory工厂方法来创建类,类必须有默认构造函数,如果没有,需要Poco::Instantiator来辅助实现。

6.2 用法

#include "Poco/DynamicFactory.h"
using Poco::DynamicFactory;
using Poco::AbstractInstantiator;
class Base {};
class A: public Base {};
class C: public Base
{
public:
	C(int i): _i(i){}
private:
	int _i;
};

class CInstantiator: public AbstractInstantiator<Base>
{
public:
	CInstantiator(int i): _i(i){}
	Base* createInstance() const { return new C(_i);}
private:
	int _i;
}

int main(int argc, char** argv)
{
	DynamicFactory<Base> factory;
	factory.registerClass<A>("A");
	factory.registerClass("C", new CInstantiator(42));
	return 0;
}

7、Poco::Buffer 缓冲区管理

7.1 说明

当与遗留的C库或操作系统调用接口时,通常需要提供一定大小的缓冲区。
如果缓冲区大于几个字节,则必须在堆上分配。
这需要某种类型的内存管理,以确保缓冲区在不再使用时被删除,即使在异常的情况下。
std::auto_ptr或Poco::SharedPtr(具有默认的发布策略)不能在这里使用,因为它们不适用于数组。

Poco::Buffer可用于提供固定大小的缓冲区(数组),该缓冲区在堆上分配,并在Buffer对象超出作用域时自动删除。

7.2 用法

头文件:#include “Poco/Buffer.h”

  • begin()方法返回一个指向缓冲区开头的指针。
  • end()方法返回一个指向缓冲区末尾的指针。
  • 索引操作符提供对缓冲区中单个元素的访问。
#include <Poco/Buffer.h>
#include <string>
#include <iostream>
using Poco::Buffer;
int main(int argc, char** argv)
{
	Buffer<char> buffer(1024);
	std::cin.read(buffer.begin(), buffer.size());
	std::streamsize n = std::cin.gcount();
	std::string s(buffer.begin(), n);
	std::cout << s << std::endl;
	return 0;
}

8、Poco::MemoryPool 内存池

8.1 说明

许多应用程序需要非常频繁地分配和释放给定大小的缓冲区。
在堆上分配缓冲区会影响性能,并可能导致堆碎片。
因此,一旦缓冲区被分配,重用它是有意义的。
Poco::MemoryPool 是一个内存池,一次分配,多次使用,维护一定大小的内存块集合

8.2 用法

  • void* MemoryPool::get():从内存池中获取一个指向连续内存块的指针。如果没有可用的块,则分配一个新的块。可以限制块的最大数量。如果没有更多的块可用,则抛出OutOfMemoryException。
  • void MemoryPool::release(void* ptr):将内存块释放回内存池。
#include "Poco/MemoryPool.h"
#include <string>
#include <iostream>
using Poco::MemoryPool;
int main(int argc, char** argv)
{
	MemoryPool pool(1024); // unlimited number of 1024 byte blocks
	// MemoryPool pool(1024, 4, 16); // at most 16 blocks; 4 preallocated
	char* buffer = reinterpret_cast<char*>(pool.get());
	std::cin.read(buffer, pool.blockSize());
	std::streamsize n = std::cin.gcount();
	std::string s(buffer, n);
	pool.release(buffer);
	std::cout << s << std::endl;
	return 0;
}

9、POCO::SingletonHolder 线程安全的单例

9.1 说明

POCO提供了一个POCO::SingletonHolder类,帮助对延迟创建的单例进行线程安全管理。
头文件:#include “Poco/SingletonHolder.h”
单例实例在第一次被请求时创建在堆上。
当应用程序终止时,单例实例被销毁。

9.2 用法

#include "Poco/SingletonHolder.h"
class MySingleton
{
public:
	MySingleton(){// ...}
	~MySingleton(){// ...}
	// ...
	static MySingleton& instance()
	{
		static Poco::SingletonHolder<MySingleton> sh;
		return *sh.get();
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/242590.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

dialog 在xml文件进行了自适应宽,但是失效了

如下图 讲述了为什么已经设置好了dialog的宽高 到了显示的时候就会失效的原因 解决方式 &#xff1a; 在自定的dialog中的onstart()方法中进行重新设置宽高 Window window getWindow();WindowManager.LayoutParams lp window.getAttributes();lp.height LinearLayout.La…

springboot使用EasyExcel导入数据

springboot使用EasyExcel导入数据 1. 引入依赖 <!-- Easy Excel --> <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.2.1</version> </dependency>2. 建立对应实体类 假如…

Visual Studio使用Web Deploy发布.NET Web应用到指定服务器的IIS中

前言 今天要讲的是在Window 2008 R2版本的服务器下如何配置Web Deploy&#xff0c;和Visual Studio使用Web Deploy发布.NET Web应用到指定服务器的IIS中。 因为历史原因项目只能使用这个版本的服务器&#xff0c;当然使用其他服务器版本配置流程也是一样的。 Web Deploy介绍 …

Oracle数据库对SAP的支持

其实有时候&#xff0c;很多信息都已经整理好了&#xff0c;你只需要知道他在哪里就好&#xff0c;无需自己整理。 Oracle数据库对SAP的支持&#xff0c;可以从这个网页快速了解。 看前面的概述&#xff1a; Oracle 数据库是全球 SAP 客户中排名第一的数据库&#xff0c;拥有…

插入算法(C语言)

#include<cstdio> #include<iostream> #define N 9 using namespace std; int main() {int arr[N1] { 1,4,7,13,16,19,22,25,280 }; int in,i,j;//要插入的数字//打印要插入数字的数组所有元素printf("插入前的数组: ");for ( i 0; i <N; i){print…

设计模式——单例模式(创建型)

引言 单例模式是一种创建型设计模式&#xff0c; 让你能够保证一个类只有一个实例&#xff0c; 并提供一个访问该实例的全局节点。 问题 单例模式同时解决了两个问题&#xff0c; 所以违反了单一职责原则&#xff1a; 保证一个类只有一个实例。 为什么会有人想要控制一个类所…

回归预测 | MATLAB实现CHOA-BiLSTM黑猩猩优化算法优化双向长短期记忆网络回归预测 (多指标,多图)

回归预测 | MATLAB实现CHOA-BiLSTM黑猩猩优化算法优化双向长短期记忆网络回归预测 &#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现CHOA-BiLSTM黑猩猩优化算法优化双向长短期记忆网络回归预测 &#xff08;多指标&#xff0c;多图&#xff09;效果…

YOLOv8改进 | 2023主干篇 | EfficientViT替换Backbone(高效的视觉变换网络)

一、本文介绍 本文给大家带来的改进机制是EfficientViT&#xff08;高效的视觉变换网络&#xff09;&#xff0c;EfficientViT的核心是一种轻量级的多尺度线性注意力模块&#xff0c;能够在只使用硬件高效操作的情况下实现全局感受野和多尺度学习。本文带来是2023年的最新版本…

是谁,在参与数十亿美元的量子市场?

量子技术是最不为人们所了解、但却最有希望在未来几年颠覆商业和产业的进步技术之一。 很少有像量子信息科学市场这样小的市场能引起如此热烈的讨论。上周&#xff0c;根据Hyperion Research在圣克拉拉举行的Q2B硅谷会议上发布的年度量子计算&#xff08;QC&#xff09;市场更新…

【开源软件】最好的开源软件-2023-第23名 Apache Druid

自我介绍 做一个简单介绍&#xff0c;酒架年近48 &#xff0c;有20多年IT工作经历&#xff0c;目前在一家500强做企业架构&#xff0e;因为工作需要&#xff0c;另外也因为兴趣涉猎比较广&#xff0c;为了自己学习建立了三个博客&#xff0c;分别是【全球IT瞭望】&#xff0c;【…

Git使用——IDEA中git branch显示乱码 后面提示standard input 如何解决

问题描述&#xff1a; idea中的terminal中输入git branch显示乱码 解决方案 在idea的file里面&#xff0c;进行设置 选择安装的git下面的bash 参考博客&#xff1a; https://blog.csdn.net/weixin_39925939/article/details/122410453

使用 Timm 库替换 YOLOv8 主干网络 | 1000+ 主干融合YOLOv8

文章目录 前言版本差异说明替换方法parse_moedl( ) 方法_predict_once( ) 方法修改 yaml ,加载主干论文引用timm 是一个包含最先进计算机视觉模型、层、工具、优化器、调度器、数据加载器、数据增强和训练/评估脚本的库。 该库内置了 700 多个预训练模型,并且设计灵活易用。…

算法基础之树的重心

树的重心 无向图: 边没有方向 有向图:边有方向 只能单向询问 无向图建立双向的边 要求输出每种情况连通块个数最大值的最小值**(最小的最大值)** #include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace s…

开发案例:使用canvas实现图表系列之折线图

一、功能结构 实现一个公共组件的时候&#xff0c;首先分析一下大概的实现结构以及开发思路&#xff0c;方便我们少走弯路&#xff0c;也可以使组件更加容易拓展&#xff0c;维护性更强。然后我会把功能逐个拆开来讲&#xff0c;这样大家才能学习到更详细的内容。下面简单阐述…

一个Redis实例最多能存放多少keys

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

【Qt QML入门】Image

Image类型显示一个图像。 使用source属性将图像的源指定为URL。图像可以以Qt支持的任何标准图像格式提供&#xff0c;包括位图格式&#xff0c;如PNG和JPEG&#xff0c;以及矢量图形格式&#xff0c;如SVG。 如果没有指定宽度和高度属性&#xff0c;图像将自动使用加载图像的大…

如果我忽然嗝屁了,家人怎么继承我的财产

前言 笔者很喜欢的电影《寻梦环游记》有这么一句经典台词&#xff1a;“真正的死亡是世界上没有一个人记得你”。 然而&#xff0c;现实中我们所说的“死亡”&#xff0c;其实就是 他再不能与这个世界、与自己在乎的人有新的互动了。 本文&#xff0c;笔者想写一写 关于死亡的…

iOS16.5 以上12小时制/24小时制 HH/hh引起的时间计算错误

iOS16.5以上的版本&#xff0c;如果用yyy-MM-dd HH:mm:ss转换时间&#xff0c;则有肯能发生错误。 先上代码&#xff1a; NSString * timeStr "2023-01-01 11:13:32"; NSDateFormatter * dateFormatter [[NSDateFormatter alloc] init]; [dateFormatter setDateFo…

windows10下jdk安装

文章目录 windows10下jdk安装说明what安装包下载执行安装包验证是否安装成功 windows10下jdk安装 说明 操作系统&#xff1a;windows10 版本&#xff1a;1.8 what JDK(Java Development Kit) 是 Java 语言的软件开发工具包 安装包下载 https://www.oracle.com/java/techn…

Proxmox服务安装

文章目录 系统盘制作 TODO安装系统安装Proxmox系统安装wpa服务配置wifi通过IP访问Proxmox创建服务器配置服务器网络连接虚拟机方式第一种方法&#xff1a;通过建设OpenVPN方式连接虚拟机第二种方法&#xff1a;通过端口转发直连虚拟机设置安装ubuntu服务器允许root用户远程登录…
最新文章