具有动态项目大小的C++向量

C++ vector with dynamic item size

本文关键字:C++ 向量 动态 项目      更新时间:2023-10-16

C++STL向量有很多不错的属性,但只有在运行时知道每个项的大小时才有效。

我想要一个向量类,它在运行时具有动态项目大小的特性。

背景:我的项目由一系列整数和双打组成;只有在运行时才知道的序列。只要在运行时给向量给定每个项目的大小就足够了。

我知道可能的解决方案,但这些往往不能反映算法的基本思想,这对维护来说总是一件坏事。有没有像人们所期望的那样提供方便和工作效率的课程?

编辑:

这与整个数组中项目大小的变化无关。这与无关。它在运行时决定数组中的项有多大;即与模板一起使用的静态类型相比,动态类型的(非常)弱的形式。

因此,对象的初始化应该是这样的:

DynamicVector V( lengthofvector, sizeofelement );

一个应用是单纯网格。对象$V$包含固定大小或"类型"的项,每个项都由拓扑信息的整数和一些几何信息的双值组成。甚至可能会出现嘘声,但到目前为止,这是无关紧要的。

问题是,如果你没有办法将每个项目的大小存储在向量中,你将永远无法取回数据。

将所有项目存储为double怎么样?这大大简化了事情。

或者,您可以考虑boost::variant

编辑:但你真的能进一步解释为什么你想在同一序列中存储两种不同的类型吗?这有时可能表明底层设计需要进一步思考。

您可以使用指向序列对象的vector指针(最好是智能指针)来简化矢量中的内存管理。

如果它只是intdouble的序列,那么您可以简单地使用:

 std::vector<double> sequence;

然后将intdouble插入其中。然而,这种方法没有跟踪项目的类型。如果类型对您至关重要,那么以下可能会对您有所帮助:

struct item
{
  union 
  {
     int i;
     double d;
  } data;
  char type; //store 0 for int, 1 for double;
};
std::vector<item> sequence;

当然,这种方法为每个项目至少花费一个额外字节,用于存储项目的类型。您可能需要使用#pragma pack技术来挤压额外的填充。

或者更好的方法是重新设计你的代码,使你有两个序列而不是一个:

std::vector<int>     intSeq;
std::vector<double>  doubleSeq;

向量表示内存中的连续数组。这是有效的,因为它可以使用指针算法通过索引直接访问元素。但这样做意味着所有元素都有相同的大小,并且在构建向量之前要知道这个大小。

根据您的需要,可以使用指向元素的指针向量,也可以使用双链表。指针的矢量几乎和矢量一样快。它只需要一种模式的尊重。

如果整数和双精度相同(例如64位),则可以使用并集以整数或双精度访问每个项。但你需要一种方法来知道每个元素应该是什么。

如果你不想求助于的变通方法,我认为你应该考虑对那些"动态大小的项目"进行抽象。它的设计应该考虑到它必须在STL向量中使用(然后必须保证一些必要条件),这样你就可以最终编写这样的东西:

std::vector<DynamicSizedItem> myVector;

创建一个包含三个向量的类:一个用于int,一个用于doubles,一个为每个项都有一个条目,用于告诉相应项的类型及其在相应向量中的索引。

使用std::vector,其中item是一个换行的智能指针。"item"类使指针看起来像一个普通值:

class item {
private:
    boost:unique_ptr<base> p;
public:
    // ...
    public item(item that);
    public int someFunction() {
       // Forwarded
       return p->somefunction();
    }
};
class base {
    virtual ~base();
    // This is needed in order to implement copy of the item class
    virtual base* clone();
};
public item::item(item that) : p(that.p.clone()) {}
class some_real_type() : public base {
   // ....
}

我认为最好的方法(就性能和可维护性而言)是一种变通方法,将std::vector和std::vector封装在两个类中,这两个类用适当的接口插入一个公共基类。

如果你希望它在运行时是动态的,那就是正确的方法。它还可以帮助您编写高效的代码来处理每个项目,以及简单地(但缓慢地)访问每个元素。

我以前见过这个问题!是否有一个STL容器在运行时指定元素大小的连续内存中存储元素数组?

Guy想要一个"交错向量"(他的话),它可以容纳动态大小的对象,由成员类型和偏移的映射定义:

typedef Toffset uint; //byte offset;
typedef Ttype   uint; //enum of types
typedef std::pair<Toffset,Ttype> member;
typedef std::unordered_map<std::string, member> memberdefs;

我想出了一个(未经测试的)类来处理这个问题。完整的代码在链接中,但原型是:

class interleaved_vector {
    const char* buffer;
    size_t count;
    size_t size;
    std::shared_ptr<memberdefs> members;
public: 
    class dynamic_object {
        const char* buffer;
        std::shared_ptr<memberdefs> members;
        friend interleaved_vector;
        dynamic_object(const char* buffer_, std::shared_ptr<memberdefs> members_);
        dynamic_object& operator=(const dynamic_object& b) = delete;
    public:
        dynamic_object(const dynamic_object& b) ;
        template <class T>
        T get(const std::string& member) const;
        template <>
        T* get<T*>(const std::string& member) const;
        void* operator[](const std::string& member) const;
    };
    interleaved_vector(const char* buffer_, size_t count_, size_t size_, const memberdefs& members_);
    dynamic_object get(size_t index) const;
    dynamic_object operator[](size_t index) const;
    size_t size();
};

作为警告:它确实依赖于一些我认为未定义的行为,总的来说,这是一个坏主意。使用指针向量。