我希望从一个池分配一个shared_ptr管理的对象,比如Boost的Pool接口,怎么能实现呢?
我在大型应用程序中工作,包含c和cpp.所有文件都保存为cpp扩展名,但代码以c风格编写.我的意思是它是定义结构而不是类通过malloc和realloc和calloc分配内存.最近他们已经安装了boost库所以我打算使用我现有的代码库所以我有一些以下的问题.
或者换句话说:
对于以下代码,如何使用std :: shared_ptr实现类似功能:
void allocateBlocks(int **ptr, int *cnt)
{
*ptr = (int*)malloc(sizeof(int) * 10);
*cnt = 10;
/*do something*/
}
int main()
{
int *p = NULL;
int count = 0;
allocateBlocks(&p, &count);
/*do something*/
free(p);
}
Run Code Online (Sandbox Code Playgroud)
我们调用一些函数,它们接受双指针并在其应用程序中填充结构并使用malloc.我们可以将这些指针分配给std :: shared_ptr吗?例如:
typedef struct txn_s
{
int s;
int d;
int *e;
} txn_t;
typedef boost::shared_ptr<txn_t> tpointer;
tpointer((txn_t*)::malloc(sizeof(txn_t),::free));
Run Code Online (Sandbox Code Playgroud) RCObject"引用计数对象"的类;RCObject应该是抽象的,作为框架的基类(EC++ 3 Item 7);RCObject应禁止在堆栈上创建子类的实例(MEC++ 1 Item 27);
[ 增加: ]
[假设Bear是RCObject] 的具体子类
[ C.E.这里表示编译错误]
Bear b1; // Triggers C.E. (by using MEC++1 Item 27)
Bear* b2; // Not allowed but no way to trigger C.E.
intrusive_ptr<Bear> b3; // Recommended
Bear* bs1 = new Bear[8]; // Triggers C.E.
container< intrusive_ptr<RCObject> > bs2; // Recommended
intrusive_ptr_container<RCObject> bs3; // Recommended
class SomeClass {
private:
Bear m_b1; // Triggers …Run Code Online (Sandbox Code Playgroud)由于我的noob声誉,我无法回复此主题,特别是接受的答案:
我从未使用过boost :: intrusive智能指针,但如果你使用shared_ptr智能指针,你可以使用weak_ptr对象作为缓存.
当系统决定释放内存时,那些weak_ptr指针不算作引用,但只要该对象尚未被删除,它就可用于检索shared_ptr.
这当然是一个直观的想法,但是,C++标准不支持weak_ptrs的比较,因此它不能用作关联容器的键.这可以通过为weak_ptrs实现比较运算符来规避:
template<class Ty1, class Ty2>
bool operator<(
const weak_ptr<Ty1>& _Left,
const weak_ptr<Ty2>& _Right
);
Run Code Online (Sandbox Code Playgroud)
这个解决方案的问题是
(1)比较运算符必须获得每次比较的所有权(即从weak_ptr refs创建shared_ptrs)
(2)当管理资源的最后一个shared_ptr被破坏时,weak_ptr不会从缓存中删除,但是过期的weak_ptr会保留在缓存中.
对于(2),我们可以提供自定义析构函数(DeleteThread),但是,这将需要再次从要删除的T*创建weak_ptr,然后可以使用它从缓存中擦除weak_ptr.
我的问题是,如果有更好的方法使用智能指针缓存(我使用VC100编译器,没有提升),或者我根本没有得到它?
干杯,丹尼尔
我一直在评估各种智能指针实现(哇,有很多),在我看来,大多数可以分为两大类:
1)此类别对引用的对象使用继承,以便它们具有引用计数,并且通常实现up()和down()(或它们的等价物).IE,要使用智能指针,您指向的对象必须从ref实现提供的某些类继承.
2)此类别使用辅助对象来保存引用计数.例如,不是将智能指针指向对象,而是实际指向此元数据对象...谁具有引用计数以及up()和down()实现(并且通常为指针提供一种机制)获取指向的实际对象,以便智能指针可以正确实现operator - >()).
现在,1有一个缺点,它强制你想引用的所有对象计数从一个共同的祖先继承,这意味着你不能使用它来引用你无法控制源代码的计数对象至.
2有一个问题,因为计数存储在另一个对象中,如果你有一个指向现有引用计数对象的指针被转换为引用的情况,你可能有一个错误(IE,因为计数不在实际的对象,新的引用没有办法得到计数...引用ref复制构造或赋值是好的,因为它们可以共享count对象,但如果你必须从指针转换,你'完全被冲洗了)...
现在,正如我所理解的那样,boost :: shared_pointer使用了机制2,或类似的东西......那就是说,我不能完全决定哪个更糟糕!我只使用机制1,在生产代码中......有没有人有这两种风格的经验?或许还有另一种方式比这两种方式更好?
我有一个应用程序有几个对象(目前约有50个,但正在增长).应用程序中每个对象只有一个实例,这些实例在组件之间共享.
我所做的是从基础BrokeredObject类派生所有对象:
class BrokeredObject
{
virtual int GetInterfaceId() = 0;
};
Run Code Online (Sandbox Code Playgroud)
每个对象类型都返回一个唯一的ID.这些ID保存在头文件中.
然后我有一个ObjectBroker"工厂".当有人需要一个对象时,请调用GetObjectByID().boker在STL列表中查看该对象是否已存在,如果存在,则返回该对象.如果没有,它会创建它,将其放入列表并返回它.一切都很好.
BrokeredObject *GetObjectByID(int id)
{
BrokeredObject *pObject;
ObjectMap::iterator = m_objectList.find(id);
// etc.
if(found) return pObject;
// not found, so create
switch(id)
{
case 0: pObject = new TypeA; break;
case 1: pObject = new TypeB; break;
// etc.
// I loathe this list
}
// add it to the list
return pObject;
}
Run Code Online (Sandbox Code Playgroud)
我觉得痛苦的是维护这个ID列表并让每个类实现它.我至少让我的消费者的生活变得更容易了,让每个类型都拥有关于它自己的ID的信息,如下所示:
class TypeA : public BrokeredObject
{
static int get_InterfaceID() { return IID_TYPEA; }
int …Run Code Online (Sandbox Code Playgroud) 我一直在尝试使用智能指针来升级现有的应用程序,而我正试图克服一个难题.在我的应用程序中,我有一个对象缓存,例如我们称之为书籍.现在,这些书籍缓存是由ID请求的,如果它们在缓存中,则返回它们,如果不是,则从外部系统请求对象(慢速操作)并将其添加到缓存中.一旦进入缓存,可以在应用程序中打开许多窗口,每个窗口都可以参考该书.在以前版本的应用程序中,程序员必须维护AddRef和Release,当每个使用Book对象的窗口关闭时,最终Release(在缓存管理器上)将从缓存中删除对象并删除对象.
您可能已经在链中发现了弱链接,当然程序员记得要调用AddRef和Release.现在我已经转向智能指针(boost :: intrusive)我不再需要担心调用AddRef和Release.然而,这会导致问题,缓存具有对对象的引用,因此当最终窗口关闭时,不通知缓存没有其他人持有引用.
我的第一个想法是定期遍历缓存并清除引用计数为1的对象.我不喜欢这个想法,因为它是一个N阶操作并且感觉不对.我想出了一个回调系统,这个系统更好但不是很棒.我已经包含了回调系统的代码,但我想知道是否有人有更好的方法这样做?
class IContainer
{
public:
virtual void FinalReference(BaseObject *in_obj)=0;
};
class BaseObject
{
unsigned int m_ref;
public:
IContainer *m_container;
BaseObject() : m_ref(0),m_container(0)
{
}
void AddRef()
{
++m_ref;
}
void Release()
{
// if we only have one reference left and we have a container
if( 2 == m_ref && 0 != m_container )
{
m_container->FinalReference(this);
}
if( 0 == (--m_ref) )
{
delete this;
}
}
};
class Book : public BaseObject
{
char *m_name; …Run Code Online (Sandbox Code Playgroud) 我正在std::shared_ptr<void>我的应用程序中使用一个智能指针,它可以指向许多不同类型的数据结构,如结构,向量,矩阵......基本上任何东西.我要做的是将一些名称映射到他们的数据结构.
我正在使用哈希表执行映射:
std::unordered_map<std::string, std::shared_ptr<void>>
我可以把std::shared_ptr<void>返回的人投find()回去std::shared_ptr<my_type>吗?如果是这样,怎么样?
更重要的是,这是一种好的做法吗?随着应用程序的扩展,这会增加复杂性吗?或者,还有其他一些完全不同,优雅的方法吗?
编辑
可能不能使用`Boost.Any',因为它使用RTTI.
也不能为所有这些数据结构使用基类,因为它们中的一些是STL容器std::vector.
关于在shared_ptr下面的答案中讨论的删除问题,我读到shared_ptr执行类型擦除并存储类型信息以知道要调用的析构函数.
但我不确定这一点.
我正在寻找一种清洁指针的正确方法.这里是示例代码:
class Parent {
protected:
int m_Var;
public:
Parent() : m_Var(0) {}
virtual ~Parent() {}
void PubFunc();
};
class Child : public Parent {
protected:
bool m_Bool;
public:
Child() : m_Bool(false) {}
virtual ~Child() {}
void ChildFunc();
};
void RemoveObj(Parent **ppObj)
{
*ppObj->PubFunc();
delete *ppObj;
ppObj = NULL;
}
int main()
{
Parent* pPObj = NULL;
Child* pCObj = NULL;
pPObj = new Parent();
pCObj = new Child();
RemoveObj(&pPObj);
RemoveObj(&pCObj); // This is line 33
return 1;
}
Run Code Online (Sandbox Code Playgroud)
但是编译器给出了错误:
classes.cpp:33: …Run Code Online (Sandbox Code Playgroud) 按照这个页面的建议,我试图让shared_ptr调用IUnknown :: Release()而不是delete:
IDirectDrawSurface* dds;
... //Allocate dds
return shared_ptr<IDirectDrawSurface>(dds, mem_fun_ref(&IUnknown::Release));
Run Code Online (Sandbox Code Playgroud)
错误C2784:'std :: const_mem_fun1_ref_t <_Result,_Ty,_Arg> std :: mem_fun_ref(_Result(__ thishisall _Ty ::*)(_ Arg)const)':无法推断'_Result的模板参数(__thiscall _Ty ::*) (_Arg)const'from'ULONG(__ cdecl IUnknown ::*)(void)'
错误C2784:'std :: const_mem_fun_ref_t <_Result,_Ty> std :: mem_fun_ref(_Result(__ thishisall_Ty ::*)(void)const)':无法推断'_Result的模板参数(__thiscall _Ty ::*)(void )'''来自'ULONG(__ cdecl IUnknown ::*)(void)'
错误C2784:'std :: mem_fun1_ref_t <_Result,_Ty,_Arg> std :: mem_fun_ref(_Result(__ thiscall _Ty ::*)(_ Arg))':无法推断出'_Result(__thiscall _Ty ::*)的模板参数( _Arg)'from'ULONG(__ cdecl IUnknown ::*)(void)'
错误C2784:'std :: mem_fun_ref_t <_Result,_Ty> std :: mem_fun_ref(_Result(__ thishisall _Ty ::*)(void))':无法推断'_Result的模板参数(__thiscall _Ty ::*)(void) 'from'ULONG(__ cdecl IUnknown ::*)(void)' …
我正在使用Xerces做一些xml写作.
这是从我的代码中提取的几行:
DOMLSSerializer *serializer = ((DOMImplementationLS*)implementation)->createLSSerializer();
serializer->release();
Run Code Online (Sandbox Code Playgroud)
有没有我可以使用的boost智能指针,所以我可以避免调用serializer-> release(); 因为它不是例外安全.我看到的问题是,智能指针只能调用指针对象上的delete,是否可以自定义调用release?
谢谢
c++ ×11
boost ×6
shared-ptr ×5
caching ×2
pointers ×2
polymorphism ×2
allocator ×1
c++03 ×1
c++11 ×1
directx ×1
inheritance ×1
raii ×1
scoped-ptr ×1
stl ×1
weak-ptr ×1