简体   繁体   中英

Fixed size std::vector at runtime?

Performance is crucial in my application

I need something that works like std::experimental::dynarray , so an array which size is decided at runtime.

So I thought about using a wrapper class for std::vector , giving all its features, but without the possibility to call resize , reserve or push_back . In few words, all the methods to change its size (please remind me if I missed some of them).

So I started writing this class:

CCVector.hpp :

template <typename T>
class CCVector{
public:
    CCVector(size_t size);
    T &operator[](typename std::vector<T>::size_type idx);
private:
    std::vector<T> v;
};

CCVector.cpp :

template<typename T>
CCVector<T>::CCVector(size_t size) : v(size){}
template<typename T>
T& CCVector<T>::operator[](typename std::vector<T>::size_type idx){
    return  v[idx];
}

But I this point I thought I have to re-implement every method of std::vector that I need! For example begin , end , size etc, and I don't know how to implement all of them...Besides, this is really bad for maintenance: as soon as I need a new method from std::vector I need to re-implement it in CCVector .

All of this because I want fixed size arrays at runtime. How can I solve this without using the non-standard std::experimental::dynarray ?

Use private inheritance and then import the functions you want using the using declaration to introduce the names you want into your class.

template<class T>
class MyVector : private std::vector<T>
{
public:
    using std::vector<T>::end;
    // etc
};

(With private inheritance you don't get the issue with vector not having a virtual destructor which is the reason most people don't like inheriting from standard containers)

You are right that std::vector has quite a few member functions that you need to expose to the outside, but there are not thaaat many. For example, see here http://www.cplusplus.com/reference/vector/vector/

Furthermore, you do not need to (and should not) reimplement std::vector on your own - relying on tested, fast code like your STL is almost always the better option.

So, instead of reimplementing, simply "forward" the functions to the outside, like so:

iterator begin()
{
   return v.begin();
}

This is a bit of boilerplate code, but if you do this once for the non-resizing functions of std::vector , you are done.

Edit:

Also, do not inherit from std::vector . This is a bad idea for many reasons.

Okay, I was a bit quick here, sorry for that. As the comments, and this post suggest, inheriting from an STL container is not inherently bad. Particularly if you use private inheritance, it might just be a valid solution for the given task.

Privately inheriting std::vector is as proposed in the other answer is one approach.

There is some memory overhead for using resizable container where a non-resizable would suffice. std::vector is typically around ~4 x size of a data pointer. You can store a pointer to data + length in half of that:

template<class T>
class dynarray
{
    std::unique_ptr<T[]> data;
    T*                   end; // or size_t size

    //TODO functions
};

The downside obviously is that you must re-implement all of the boilerplate, that you could otherwise inherit from std::vector . That said, all of the boilerplate is quite trivial - there is just lots of it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM