POCO
类型和字节顺序
固定大小整数类型
POCO定义固定大小的整数
#include "Poco/Types.h"
已经被自动包含到Poco/Foundation.h头文件中,含有
Poco::Int8,Poco::Int16,Poco::Int32,Poco::Int64
Poco::Uint8.Poco::UInt16,Poco::UInt32,Poco::UInt64
Poco::IntPtr,Poco::UIntPtr是和(32位或64位)系统指针相同大小的整数
内置类型的大小
POCO有两个宏定义来确定long类型和指针类型的大小
POCO_PTR_IS_64_BIT:如果指针为64位,则定义宏
POCO_LONG_IS_64_BIT:如果long型为64位,则定义宏
字节顺序
POCO 可以处理字节顺序问题
POCO有用于处理当前主机字节序的宏
- POCO_ARCH_LITTLE_ENDIAN:小端的宏定义
- POCO_ARCH_BIG_ENDIAN:大端的宏定义
类Poco::ByteOrder提供了字节顺序转换的静态方法
头文件:#include"Poco/ByteOrder.h"
IntXX flipBytes(IntXX value)
函数作用:将字节顺序从大端转为小端,反之亦然
字节顺序转换
IntXX toBigEndian(IntXX value)
函数作用:从主机字节序转化成大端序
IntXX toLittleEndian(IntXX value)
函数作用:从主机序转化成小端序
IntXX fromBigEndian(IntXX value)
函数作用:从大端序准转化成主机序
IntXX fromLittleEndian(IntXX value)
函数作用:从小端序转化为主机序
IntXX toNetwork(IntXX value)
函数作用:从本地字节序转化成网络字节序
IntXX fromNetwork(IntXX value)
函数作用:从网络字节序转化成本地字节序
网络字节序为大端序,以上方法均为内联方法
实例演示
#include "Poco/ByteOrder.h"
#include <iostream>
using Poco::ByteOrder;
using Poco::UInt16;
int main(int argc, char** argv)
{
#ifdef POCO_ARCH_LITTLE_ENDIAN
std::cout << "little endian" << std::endl;
#else
std::cout << "big endian" << std::endl;
#endif
UInt16 port = 80;
UInt16 networkPort = ByteOrder::toNetwork(port);
return 0;
}
任意类型(Any Type)
头文件:#include"Poco/Any.h"
作用:Poco::Any的值可以保存任何内置或者用户定义类型的值,且Poco::Any支持值语义,同时可以以类型安全的方式提取该值,为了提取它这个值必须已知
Poco::AnyCast()和Poco::RefAnyCast()函数模板用于提取值
#include "Poco/Any.h"
#include "Poco/Exception.h"
using Poco::Any;
using Poco::AnyCast;
using Poco::RefAnyCast;
int main(int argc, char** argv)
{
Any any(42);
int i = AnyCast<int>(any); // okay
int& ri = RefAnyCast<int>(any); // okay
try
{
short s = AnyCast<short>(any); // throws BadCastException
}
catch (Poco::BadCastException&)
{
}
return 0;
}
动态任意类型(The DynamicAny Type)
头文件:include"Poco/DynamicAny.h"
支持安全的隐式和显示转换为任何类型(标准类型,std::string)
DynamicAny - 转换规则
- 数字值不允许数据丢失精度
- 值小于零永远不会转换为无符号类型
- 如果需要x位的值,将永远不会转换为更小的位范围
- 允许int到float和back的精度丢失
- 允许字符串截断
#include "Poco/DynamicAny.h"
#include "Poco/Exception.h"
using Poco::DynamicAny;
int main(int argc, char** argv)
{
DynamicAny any(42);
int i = any;
std::string s(any.convert<std::string>());
any.convert(s); // or without the need to cast
const int& ri(any.extract<int>());
short s = any;
try
{
short s = any.extract<short>(); // throws BadCastException
}
catch (Poco::BadCastException&)
{
}
return 0;
}
存储管理(Memory Management)
引用计数,共享指针,缓冲区管理等
引用计数
作用:每当一个引用被摧毁或者被重写,引用计数会减少
每当一个引用被创建或者被复制,引用计数会增加
引用计数的初始值为1
当引用计数为0时,会销毁对象
在多线程场景中,递增和递减/比较引用计数器必须是原子操作
对象所有权
拥有对象的所有权的对象也需要在不再需要这个对象时释放所有权
如果对象的拥有者没能释放这个对象,这将导致内存泄露
可能也会有其他指向该对象,但是他们永远不会删除对象
对象的所有权可以进行转让,但是同一时刻只有一个拥有对象所有权
引用计数和对象所有权
拥有引用计数所有权的指针不会增加引用计数
- 这意味着没有以前的所有者(换句话说,对象刚刚被创建)
- 或者之前的所有者放弃了所有权(因此没有减少对象的引用计数)
THE AUTOPTR CLASS TEMPLATE
Poco::AutoPtr实现了一个引用计数智能指针
任何支持引用计数的类都能支持Poco::AutoPtr的实例化
#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
AutoPtr 运算符和语义
Poco::AutoPtr支持关系运算符:==,!=,<,<=,>,>=
重定义了运算符:*,->
如果指针为空将会抛出NullPointerExcepttion如果指针为空
Poco::AutoPtr支持全值语义(默认构造函数,复制构造函数,赋值)可以在集合中使用
使用AutoPtr::isNull()或者AutoPtr::operator!()去测试空指针
AutoPtr和类型
和普通指针一样,Poco::AutoPtr支持强制类型转换
#include "Poco/AutoPtr.h"
#include "Poco/RefCountedObject.h"
class A: public Poco::RefCountedObject {};
class B: public A {};
class C: public Poco::RefCountedObject {};
int main(int argc, char** argv)
{
Poco::AutoPtr<A> pA;
Poco::AutoPtr<B> pB(new B);
pA = pB; // okay, pB is a subclass of pA
pA = new B;
// pB = pA; // will not compile
pB = pA.cast<B>(); // okay
Poco::AutoPtr<C> pC(new C);
pA = pC.cast<A>(); // pA is null
return 0;
}
AutoPtr注意事项和陷阱
将AutoPtr指定给普通指针,然后将普通指针指定给另一个AutoPtrs时,请格外小心!
两个指针都会声明对对象的所有权
#include "Poco/AutoPtr.h"
#include "Poco/RefCountedObject.h"
class A: public Poco::RefCountedObject
{
};
int main(int argc, char** argv)
{
Poco::AutoPtr<A> p1(new A);
A* pA = p1;
// Poco::AutoPtr<A> p2(pA); // BAD! p2 assumes sole ownership
Poco::AutoPtr<A> p2(pA, true); // Okay: p2 shares ownership with p1
Poco::AutoPtr<A> p3;
// p3 = pA; // BAD! p3 assumes sole ownership
p3.assign(pA, true); // Okay: p3 shares ownership with p1
return 0;
}
AutoRealsePool
Poco::AutoRealsePool负责类模板负责(引用计数)其他人不需要的对象
头文件:#include"Poco/AutoReleasePool.h"
Poco::AutoReleasePool拥有所有添加到它的每个对象的所有权
当Poco::AutoReleasePool被摧毁时,释放所有对象的引用,通过调用Release()方法
#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;
}
// all C's deleted
SharedPtr
Poco::SharedPtr为本身没有实现引用计数的类实现应用计数
头文件:#include"Poco/SharedPtr.h"
警告
将指向同一对象的普通指针分配给不同的SharedPtr将导致对象的多个所有者发生为定义的行为(换句话说,将会崩溃)
一旦将SharedPtr用于对象,就不要再使用指向该对象的普通指针
#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; // BAD BAD BAD: multiple owners -> multiple delete
p2 = p1; // rc == 2
std::string::size_type len = p1->length(); // dereferencing with ->
std::cout << *p1 << std::endl; // dereferencing with *
return 0;
}
// rc == 0 -> deleted
动态工厂类模板(The DynamicFactory Class Template)
Poco::DynamicFactory支持按“名称”创建对象
头文件:#include “Poco/DynamicFactory.h”
DynamicFactory管理的所有类都必须有公共的基类,DynamicFactory为基类进行实例化
C* DynamicFactory::createInstance(const std::string& name)const;
创建一个拥有给出名字的C子类的实例
类及其实例化类(工厂类)必须向DynamicFactory进行注册
Poco::Instantiator是给定类的工厂模板
定义了一个方法createInstance(),该方法创建一个新的类的实例,使用new运算符
为了使用类层次结构,实例化程序总是继承自Poco::AbstractInstantiator,后者为基类定义了createInstance()
#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;
factory.registerClass<A>("A"); // creates Instantiator<A, Base>
factory.registerClass<B>("B"); // creates Instantiator<B, Base>
SharedPtr<Base> pA = factory.createInstance("A");
SharedPtr<Base> pB = factory.createInstance("B");
// you can unregister classes
factory.unregisterClass("B");
// you can also check for the existence of a class
bool haveA = factory.isClass("A"); // true
bool haveB = factory.isClass("B"); // false (unregistered)
bool haveC = factory.isClass("C"); // false (never registered)
return 0;
}