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

本文主要是介绍【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 == 1AutoPtr<RCO> p1(pNew); // _rc == 1AutoPtr<RCO> p2(p1); // _rc == 2AutoPtr<RCO> p3(pNew, true); // _rc == 3p2 = 0; // _rc == 2p3 = 0; // _rc == 1RCO* pRCO = p1; // _rc == 1p1 = 0; // _rc == 0 -> deleted// pRCO and pNew now invalid!p1 = new RCO; // _rc == 1return 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 * operatorstd::cout << "refcount: " << pRCO->referenceCount() << std::endl;RCO* p1 = pRCO; // AutoPtr supports conversion to plain pointerRCO* 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 == 1Poco::SharedPtr<std::string> p2(p1); // rc == 2p2 = 0; // rc == 1// p2 = pString; // 崩溃: 多个所有者p2 = p1; // rc == 2std::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"); // truebool 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 preallocatedchar* 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();}
}

这篇关于【C++】POCO学习总结(十四):引用计数、共享指针、缓冲区管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/491150

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名