【发布时间】:2021-05-11 22:39:52
【问题描述】:
我一直在尝试找到一种在我的项目中实现对象池的方法。我在互联网上找到了一些示例,其中大多数使用 std::lists 以及书中的示例;也使用 std::list 的游戏开发模式和最佳实践。
然而,有人告诉我,将列表用于对象池是毫无意义的,因为将对象返回池意味着必须再次分配内存。
我也看到人们使用 std::stack 但我认为存在同样的问题。
这是我按照本书的示例为对象池类编写的代码:
/* This object has only an int data type (value).
One method to se it and another one to print it. */
class Object
{
public:
Object()
{
SetValue();
std::cout << "Constructed/Reset." << std::endl;
}
// Copy constructor
Object( Object& other )
{
this->mValue = other.mValue;
std::cout << "Constructed." << std::endl;
}
~Object()
{
std::cout << "Destroyed." << std::endl;
}
void SetValue( int val = -1 )
{
mValue = val;
}
void PrintValue()
{
std::cout << this->mValue << std::endl;
}
private:
int mValue;
};
class Pool
{
public:
Pool()
{
std::cout << "Pool created!\n";
}
~Pool()
{
std::cout << "Pool destroyed!\n";
}
void Fill( int size )
{
for( int i = 0; i < size; i++ )
{
Object* obj = new Object();
pool.push_back( obj );
}
std::cout << "Objects created!" << "\nObjects in pool: "
<< pool.size() << std::endl;
}
Object* AquireObject()
{
if( !pool.empty() )
{
Object* obj = pool.back();
pool.pop_back();
std::cout << "Object aquired!"
<< "\nNumber of objects in pool: " << pool.size() << std::endl;
return obj;
}
else
{
std::cout << "Object created and aquired!"
<< "\nNumber of objects in pool: " << pool.size() << std::endl;
return new Object();
}
}
void ReleaseObject( Object* returningObject )
{
returningObject->SetValue();
pool.push_back( returningObject );
std::cout << "Object returned to the pool!"
<< "\nNumber of objects in pool: " << pool.size() << std::endl;
}
void Clear()
{
while( !pool.empty() )
{
Object* obj = pool.back();
pool.pop_back();
delete obj;
}
std::cout << "Objects deleted!"
<< "\nNumber of objects in pool: " << pool.size() << std::endl;
}
private:
std::list<Object*> pool;
};
我还制作了一个稍微不同的版本,它使用了唯一指针:
/* This object has only an int data type (value).
One method to se it and another one to print it. */
class Object
{
public:
Object()
{
SetValue();
std::cout << "Constructed/Reset." << std::endl;
}
// Copy constructor
Object( Object& other )
{
this->mValue = other.mValue;
std::cout << "Constructed." << std::endl;
}
~Object()
{
std::cout << "Destroyed." << std::endl;
}
void SetValue( int val = -1 )
{
mValue = val;
}
void PrintValue()
{
std::cout << this->mValue << std::endl;
}
private:
int mValue;
};
// Object pool using std::list
class Pool
{
public:
Pool() = default;
~Pool() = default;
/* Fills the pool (list) with a given size using an Object class (previously defined)
as a reference using its copy constructor.*/
void Fill( int size, Object* obj )
{
for( int i = 0; i < size; i++ )
{
std::unique_ptr<Object> object = std::make_unique<Object>( *obj );
pool.push_back( std::move( object ) );
}
}
// Clears all items in the list.
void PoolIsClosed()
{
pool.clear();
}
// Returns an instance of an object within the list.
std::unique_ptr<Object> GetObject()
{
if( !pool.empty() )
{
std::unique_ptr<Object> object = std::move( pool.front() );
pool.pop_front();
std::cout << "Object retrieved." << "\nObjects in pool: "
<< pool.size() << std::endl;
return object;
}
else
{
/* "WARNING: NOT ALL CONTROL PATHS RETURN A VALUE." */
std::cout << "Pool is empty." << std::endl;
}
}
// Returns an instance back to the object list.
void returnToPool( std::unique_ptr<Object> returningObject )
{
pool.push_back( std::move( returningObject ) );
std::cout << "Object returned." << "\nObjects in pool: "
<< pool.size() << std::endl;
}
private:
std::list<std::unique_ptr<Object>> pool;
};
我想知道这样的实现是否真的毫无意义,如果是,是否有一种简单的方法来实现基本的对象池类?
我知道 boost 库有自己的对象池实现……你们中有人用过吗?我很想知道更多关于它的信息,它很难使用吗?..
我还发现了这个对象池库:https://github.com/mrDIMAS/SmartPool,它看起来很有前途,而且很容易使用,但我不知道它是如何工作的,我理解起来有点复杂。对此有何看法?
【问题讨论】:
-
std::stack通常在std::vector之上实现,亚线性分配也是如此,而不是像std::list那样分配每个节点。 -
Fill可能是std::generate_n(std::back_inserter(pool), size, [](){return std::make_unique<Object>(*obj);}); -
专题教科书是学习、研究和理解这些核心算法和计算机科学主题的最佳资源。使用教科书作为学习指南,你肯定走在正确的轨道上。不要被“互联网上的几个例子”或自封专家声称的“最佳实践”分散注意力;或“被[那些]使用”其他东西的人“告诉”某事或其他事情。任何小丑都可以上传视频到 Youtube 胡言乱语;或在网站上发布一些愚蠢的东西。你应该忽略所有这些,只关注你的教科书。
-
请注意,您的
returnToPool实际上不起作用。returningObject需要作为参考传递。 -
@MooingDuck 哦,好的,我明白了......我看到使用 std::stack 的例子较少,但我值得深入研究它,谢谢你的信息!..
标签: c++ memory-management object-pooling