Create a fixed size std::vector and write to the elements

后端 未结 3 1504
滥情空心
滥情空心 2021-02-19 19:34

In C++ I wish to allocate a fixed-size (but size determined at runtime) std::vector then write to the elements in this vector. This is the code I am using:

int b         


        
相关标签:
3条回答
  • 2021-02-19 19:38

    The direct answer is that you cannot do that: you cannot define the vector as const and then add members to it.

    As others have pointed out, the new standard offers the array class, which is probably more suitable for what you are doing.

    If you are interested in a fixed length, the most related method in vector you can be interested in is reserve(), which will set the vector<> to the size of the given parameter, making vector expansions unnecessary.

    If you cannot use Std C++11, then you need to create a wrapper class that does not let you modify the vector. For example:

    #include <vector>
    #include <iostream>
    #include <exception>
    #include <stdexcept>
    using namespace std;
    
    template <typename T>
    class FinalVector {
    public:
        FinalVector(unsigned int size)
            { v.reserve( size ); }
        const T &at(unsigned int i) const
            { return v.at( i ); }
        T &at(unsigned int i)
            { return v.at( i ); }
        T &operator[](unsigned int i)
            { return at( i ); }
        const T &operator[](unsigned int i) const
            { return at( i ); }
        void push_back(const T &x);
        size_t size() const
            { return v.size(); }
        size_t capacity() const
            { return v.size(); }
    private:
        std::vector<T> v;
    };
    
    template<typename T>
    void FinalVector<T>::push_back(const T &x)
    {
        if ( v.size() < v.capacity() ) {
            v.push_back( x );
        } else {
            throw runtime_error( "vector size exceeded" );
        }
    }
    
    int main()
    {
        FinalVector<int> v( 3 );
    
        v.push_back( 1 );
        v.push_back( 2 );
        v.push_back( 3 );
    
        for(size_t i = 0; i < v.size(); ++i) {
            cout << v[ i ] << endl;
        }
    }
    

    Hope this helps.

    0 讨论(0)
  • 2021-02-19 19:59

    The actual error is because you declare the vector to be constant, meaning you can never change the contents.

    Then when you try to get a non-constant reference to an entry in the vector, the compiler tells you that you can't do that, because then you could change the constant value stored in the vector.


    As for creating a vector with a size that can be fixed at runtime, but not change size after the vector has been created, then you have to create a container adaptor. Basically you have to create a wrapper around another container, just like e.g. std::stack does.

    0 讨论(0)
  • 2021-02-19 20:04

    This is not possible without writing your own wrapper class. If you want to use a plain std::vector, you have to rely on self-discipline by not using the member functions insert(), push_back() or emplace_back(), either directly or indirectly (e.g. via a back_inserter).

    Note that there is a current proposal for dynamic arrays for the new C++14 Standard:

    [...] we propose to define a new facility for arrays where the number of elements is bound at construction. We call these dynamic arrays, dynarray.

    The proposal actually comes with a reference implementation that you can use in your own code (make sure to change namespace std into something else for the time being).

    namespace std {
    template< class T >
    struct dynarray
    {
        // types:
        typedef       T                               value_type;
        typedef       T&                              reference;
        typedef const T&                              const_reference;
        typedef       T*                              iterator;
        typedef const T*                              const_iterator;
        typedef std::reverse_iterator<iterator>       reverse_iterator;
        typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
        typedef size_t                                size_type;
        typedef ptrdiff_t                             difference_type;
    
        // fields:
    private:
        T*        store;
        size_type count;
    
        // helper functions:
        void check(size_type n)
            { if ( n >= count ) throw out_of_range("dynarray"); }
        T* alloc(size_type n)
            { if ( n > std::numeric_limits<size_type>::max()/sizeof(T) )
                  throw std::bad_array_length();
              return reinterpret_cast<T*>( new char[ n*sizeof(T) ] ); }
    
    public:
        // construct and destruct:
        dynarray() = delete;
        const dynarray operator=(const dynarray&) = delete;
    
        explicit dynarray(size_type c)
            : store( alloc( c ) ), count( c )
            { size_type i;
              try {
                  for ( size_type i = 0; i < count; ++i )
                      new (store+i) T;
              } catch ( ... ) {
                  for ( ; i > 0; --i )
                     (store+(i-1))->~T();
                  throw;
              } }
    
        dynarray(const dynarray& d)
            : store( alloc( d.count ) ), count( d.count )
            { try { uninitialized_copy( d.begin(), d.end(), begin() ); }
              catch ( ... ) { delete store; throw; } }
    
        ~dynarray()
            { for ( size_type i = 0; i < count; ++i )
                  (store+i)->~T();
              delete[] store; }
    
        // iterators:
        iterator       begin()        { return store; }
        const_iterator begin()  const { return store; }
        const_iterator cbegin() const { return store; }
        iterator       end()          { return store + count; }
        const_iterator end()    const { return store + count; }
        const_iterator cend()   const { return store + count; }
    
        reverse_iterator       rbegin()       
            { return reverse_iterator(end()); }
        const_reverse_iterator rbegin()  const
            { return reverse_iterator(end()); }
        reverse_iterator       rend()         
            { return reverse_iterator(begin()); }
        const_reverse_iterator rend()    const
            { return reverse_iterator(begin()); }
    
        // capacity:
        size_type size()     const { return count; }
        size_type max_size() const { return count; }
        bool      empty()    const { return count == 0; }
    
        // element access:
        reference       operator[](size_type n)       { return store[n]; }
        const_reference operator[](size_type n) const { return store[n]; }
    
        reference       front()       { return store[0]; }
        const_reference front() const { return store[0]; }
        reference       back()        { return store[count-1]; }
        const_reference back()  const { return store[count-1]; }
    
        const_reference at(size_type n) const { check(n); return store[n]; }
        reference       at(size_type n)       { check(n); return store[n]; }
    
        // data access:
        T*       data()       { return store; }
        const T* data() const { return store; }
    };
    
    } // namespace std
    
    0 讨论(0)
提交回复
热议问题