C++ Logo

std-proposals

Advanced search

Re: C++ create a class with array members which are not constructed.

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Wed, 2 Sep 2020 17:10:50 -0400
On Wed, Sep 2, 2020 at 2:46 PM Steve Hearnden via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> I was looking at a performance issue, with some code and found that the
> cost of creating the dynamic heap memory was the significant cost.
>
>
>
> It would have been handy to have a class which implemented something like
> std::vector, but with a **small** buffer of values to use as an
> alternative piece of memory when the vector size was below a threshold.
> [...]
>
>
>
> template< class T, size_t size>
>
> class temp_vector
>
> {
>
> [[unconstructed]] T _V[size];
>
> size_t m_constructed = 0;
>
> public:
>
> ~temp_vector()
>
> {
>
> ///// Destroy the array manually.
>
> for( size_t i = 0; i < m_constructed; i++
> ){
>
> _V[i].~T();
>
> }
>
> }
>
> }
>

I'm amazed that nobody has just given you teh codez yet. Here's basically
what you should write:

template<class T, size_t Cap>
class fixed_capacity_vector {
    alignas(T) char data_[Cap * sizeof(T)];
    size_t size_ = 0;
public:
    size_t size() const { return size_; }
    T *data() { return (T*)data_; }
    const T *data() const { return (const T*)data_; }
    T& operator[](int i) { return data()[i]; }
    const T& operator[](int i) const { return data()[i]; }
    T& push_back(const T& value) {
        assert(size_ < Cap);
        T *p = ::new ((void*)&data()[size_]) T(value);
        ++size_;
        return *p;
    }
    void pop_back() {
        back().~T();
        --size_;
    }
    fixed_capacity_vector(const fixed_capacity_vector& rhs) {
        std::uninitialized_copy(rhs.begin(), rhs.end(), data_);
        size_ = rhs.size();
    }
    fixed_capacity_vector& operator=(const fixed_capacity_vector& rhs) {
        // left as an exercise for the reader
        // also, move semantics left as an exercise for the reader
    }
    ~fixed_capacity_vector() {
        while (!empty()) pop_back();
    }
};

Notice the Rule of Three/Five here. If you provide a custom destructor, you
should also provide custom copy and move operations (or =delete them).

This is also available fully fleshed out in Boost, in the form of
boost::static_vector; and there is an active WG21 proposal, P0843,
currently targeting the Library Fundamentals v3 TS.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p0843r4.html

HTH,
Arthur

Received on 2020-09-02 16:14:31