2

目前使用我编写的库,我的小对象(不是多态的)被分配在一个对象池中,在一个带有unique_ptr's. 现在显然我想改变这一点,因为这么多次调用 new 显然有很多开销。我很好奇它是否更有效:将对象缓存在池中(将其存储在向量中,即vector<Object>),或在需要时通过其 ID 创建对象。请注意,创建了很多对象。

我的意思是,我应该这样做:

在需要时创建对象?(注意这些对象很小,64-128 位,因为只包含一个 ID 和一个指向父对象的引用/指针)

Object ObjectFactory::create()
{
    return Object(nextId(), getParent());
}

Object ObjectFactory::get(unsigned id)
{
    return Object(id, getParent());
}

或者:

Object& ObjectFactory::create()
{
     // get the next id of the object
     unsigned id = nextId();

     // resize (if necessary)
     if(_objects.size() <= id)
     {
        _objects.resize(id + 1);
        _objects[id]._parent = getParent();
     }

     return _objects[id];
}

Object& ObjectFactory::get(unsigned id)
{ return _objects[id]; }

我特别关心的是:重新创建Object' 会导致很多开销吗?

4

1 回答 1

0

@LokiAstari 是对的,您的调整大小指针显然有问题。

有什么我不明白的;你说你正在使用一个对象池,但是你有太多新语句的问题。如果您使用的是对象池,我会说这正是为了避免新的语句,不是吗?

这是我的建议,尽管我不是专家,并且通常可能有更好的解决方案涉及您自己的分配器的实现(力量的黑暗面......)。您可以使用类似 的容器std::deque,以确保指针/引用在调整大小时的有效性。

您将从大量对象(您的池)的初始调整大小开始,您可以在需要时手动处理后续调整大小(使用预定义大小的块扩展容量),或者如果您知道应该接受新的语句不是很多,并使用 emplace_back 方法。

我也不知道您是否正在使用您的 ID 插入/删除大量对象。如果是这样,您可以考虑使用std::unordered_map.

这是一个使用示例std::deque

#include <iostream>
#include <deque>

#define POOL_RESERVE 1000


// Data storage for your object
struct MyObjectData
{
    double some_data;
};


// Container returned by the factory
struct MyObject 
{
    typedef MyObjectData data_type;

    unsigned   id; 
    data_type* data;

    MyObject(): id(0), data(0) {}
    MyObject( const unsigned& id_, data_type* data_ ): id(id_), data(data_) {}

    void set( const unsigned& id_, data_type* data_ )
        { id = id_; data = data_; }
};


// MyObject Pool
class MyObjectPool
{
public:

    typedef MyObjectData data_type;

    MyObjectPool(): count(0) { pool.resize(POOL_RESERVE); }

    void get( const unsigned& id, MyObject& obj )
        {
            // Check requested index
            if ( id >= count )
                obj.set( 0, 0 );
            else
                obj.set( id, &pool[id] );
        }

    void create( MyObject& obj )
        {
            // Create new data container if needed
            if ( count++ >= pool.size() ) pool.emplace_back();

            // Return next available object
            obj.set( count-1, &pool[count-1] );
        }

private:

    unsigned count;
    std::deque<data_type> pool;
};


// MyObject factory
class MyObjectFactory
{
    typedef MyObjectFactory self;
    static MyObject local;

    static MyObjectPool& get_instance()
        {
            static MyObjectPool pool; 
            return pool;
        }

public:

    static MyObject get( const unsigned& id )
        {
            self::get_instance().get(id,local);
            return local;
        }

    static MyObject create()
        {
            self::get_instance().create(local);
            return local;
        }
};

// Define static variable
MyObject MyObjectFactory::local = MyObject();


// Usage example
int main()
{
    MyObject a,b,c;

    a = MyObjectFactory::create();
    b = MyObjectFactory::create();
    c = MyObjectFactory::get(1);
}
于 2013-02-05T15:55:45.030 回答