Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/164.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在堆栈上分配一个小对象是否比在堆上创建它(一次)更有效?_C++_Design Patterns_Objectfactory - Fatal编程技术网

C++ 在堆栈上分配一个小对象是否比在堆上创建它(一次)更有效?

C++ 在堆栈上分配一个小对象是否比在堆上创建它(一次)更有效?,c++,design-patterns,objectfactory,C++,Design Patterns,Objectfactory,目前,在我编写的库中,我的小对象(不是多态的)是在对象池中以unique\u ptr的向量分配的。现在很明显,我想改变这一点,因为在给new打这么多次电话时,显然有很多不理智的地方。我很好奇:缓存池中的对象(将其存储在向量中,即向量),或者在需要时通过其ID创建对象是否更有效。请注意,创建的对象很多 我的意思是,我应该这样做: 需要时创建对象?(请注意,这些对象很小,为64-128位,因为其中只包含一个ID和一个指向父对象的引用/指针) 或: Object&ObjectFactory::crea

目前,在我编写的库中,我的小对象(不是多态的)是在对象池中以
unique\u ptr
的向量分配的。现在很明显,我想改变这一点,因为在给new打这么多次电话时,显然有很多不理智的地方。我很好奇:缓存池中的对象(将其存储在向量中,即
向量
),或者在需要时通过其ID创建对象是否更有效。请注意,创建的对象很多

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

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

或:

Object&ObjectFactory::create()
{
//获取对象的下一个id
无符号id=nextId();
//调整大小(如有必要)

如果(_objects.size()@LokiAstari是正确的,那么很明显您在调整大小时的指针有问题

有件事我不明白,你说你在使用对象池,但是你对太多的新语句有问题。如果你在使用对象池,我会说这恰恰是为了避免新语句,不是吗

以下是我的建议,虽然我不是专家,可能有更好的解决方案涉及到您自己的分配器的实现(通常是原力的黑暗面)。您可以使用像
std::deque
这样的容器,以确保调整大小时指针/引用的有效性

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

我也不知道你是否用IDS做了很多插入/删除对象。如果是这样,你可以考虑使用<代码> STD::unOrdEdEdMult < /P> 下面是一个使用

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);
}
#包括
#包括
#定义池_储备1000
//对象的数据存储
结构MyObjectData
{
将一些数据加倍;
};
//工厂退回的集装箱
结构对象
{
typedef MyObjectData_type;
无符号id;
数据类型*数据;
MyObject():id(0),数据(0){}
MyObject(const unsigned&id_,data_type*data_):id(id_),data(data_){
无效集(常量无符号和id,数据类型*数据)
{id=id;data=data}
};
//MyObject池
类MyObjectPool
{
公众:
typedef MyObjectData_type;
MyObjectPool():计数(0){pool.resize(pool_RESERVE);}
void get(const unsigned&id、MyObject&obj)
{
//检查请求的索引
如果(id>=计数)
对象集(0,0);
其他的
对象集(id和池[id]);
}
创建空洞(MyObject和obj)
{
//如果需要,创建新的数据容器
如果(count++>=pool.size())pool.emplace_back();
//返回下一个可用对象
对象集(count-1和pool[count-1]);
}
私人:
无符号计数;
标准:德克池;
};
//MyObject工厂
类对象工厂
{
typedef myobject-factory-self;
静态肌体局部;
静态MyObjectPool&get_实例()
{
静态对象池;
回流池;
}
公众:
静态MyObject get(const unsigned&id)
{
self::get_instance().get(id,local);
返回本地;
}
静态MyObject创建()
{
self::get_instance().create(本地);
返回本地;
}
};
//定义静态变量
MyObject MyObjectFactory::local=MyObject();
//用法示例
int main()
{
对象a、b、c;
a=MyObjectFactory::create();
b=MyObjectFactory::create();
c=MyObjectFactory::get(1);
}

这个问题缺少一个细节:当您运行这两个版本时,一个版本的开销是否太大了?让我们暂时假设堆的速度比堆栈慢100倍。您的应用程序是否经常这样做,以至于它注意到了这一差异?如果不是,是否更重要的是拥有一个干净、易于使用和维护的界面?存储连续内存中的对象(std::vector保证)可以给您带来巨大的速度提升,而不是将它们存储在内存的碎片区域。我会担心这一点
\u objects.resize(id+1)
\u对象的类型是什么?
?resize将移动所有成员,从而使以前返回的所有引用无效!@miguel.martin:因为它是一个向量。调用resize()时,肯定有可能移动内部数据。如果发生这种情况,则所有引用(和迭代器)都将被移动你之前返回的是无效的。为什么要使用
std::deque
而不是
std::vector
?我想我可能会使用我选择使用的第二个选项。顺便说一句,我认为你根本不需要使用单例,只是我的意见。正如我所说,
std::vector
不能确保
调整大小后指针/引用的有效性或者一个
push_back
,这就是为什么你需要使用
std::deque
。我认为单例是必要的,因为一个池应该是可以访问的,而不需要明确地传递工厂的引用(顺便说一句,这是不清楚和危险的);任何函数或方法都应该能够事先访问池中的对象,即使我不知道您的程序。如果您的factory被意外复制,会发生什么?您是否阅读了@LokiAstari的注释?您的第二个解决方案无效。@Sh3john,我读到了。.只是不知道它在调整大小并向后推时在内部移动了对象。安d还有……这不是你让工厂不可复制的原因吗?@miguel.martin这是一种确保它确实不被复制的方法。但是想想abo
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]; }
#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);
}