C++ vector with dynamic item size

前端 未结 9 2228
无人及你
无人及你 2021-01-14 16:54

the C++ STL vector has a lot of decent properties, but only works when the size of each item is known at run-time.

I would like to have a vector class that features

相关标签:
9条回答
  • 2021-01-14 17:08

    If you don't want to resort to workarounds, I think that you should think about an abstraction of those "dynamic-sized items". It should be designed having in mind that it must be used inside a STL vector (then some requisites have to be guaranteed), such that you can finally write something like:

    std::vector<DynamicSizedItem> myVector;
    
    0 讨论(0)
  • 2021-01-14 17:11

    I've seen this question before! Is there an STL container that stores an array of elements in contiguous memory where the element size is specified at runtime?

    Guy wanted an "interleaved vector" (his word) that would hold dynamically sized objects, defined by a map of member types and offsets:

    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;
    

    And I came up with a (untested) class to handle that. The full code is in the link, but prototypes are:

    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();
    };
    

    As a warning: it does rely on some behavior that I think is undefined, and in general, is a bad idea. Go with a vector of pointers.

    0 讨论(0)
  • 2021-01-14 17:12

    vector represent a contiguous array in memory. This is efficient, since it can use pointer arithmetics to directly access elements by index. But doing that imply all elements having the same size, and to know this size before building the vector.

    For your needs, either use a vector of pointers to elements, of a double linked list. vector of pointers is almost as fast as vector. It only needs one mode deference.

    If your integers and doubles are the same size (e.g. 64 bits), you could use an union to access each item either as an integer or as a double. But you'd need a way to know what each element is supposed to be.

    0 讨论(0)
  • 2021-01-14 17:15

    I think the best way forward (in terms of performance and maintaiability) is a workaround, where you wrap std::vector and std::vector in two classes that interhit a common base class with an appropriate interface.

    If you want it dynamic at runtime, that's how to do it properly. It'd also help you write efficient code for processing each item, as well as accessing each element simply (but slowly).

    0 讨论(0)
  • 2021-01-14 17:20

    Use std::vector where item is a wrapped smart pointer. The "item" class make a pointer look like a plain value :

    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 {
       // ....
    }
    
    0 讨论(0)
  • 2021-01-14 17:21

    You could use a vector of pointers to your sequence object - preferably smart pointers, to simplify memory management in the vector.

    0 讨论(0)
提交回复
热议问题