当前位置: 首页 > 知识库问答 >
问题:

创建一个固定大小的std::vector并写入元素

姬昊焱
2023-03-14

在C中,我希望分配一个固定大小(但大小在运行时确定)的std::vector,然后写入该向量中的元素。这是我正在使用的代码:

int b = 30;
const std::vector<int> test(b);
int &a = test[3];

然而,这给了我一个编译器(MSVC 2010 Pro)错误:

错误C2440:“正在初始化”:无法从“常量int”转换为“int”

我对const的理解是,它使一个类的所有成员变量都是常量。例如,以下方法很好:

class myvec
{
public:
    myvec(int num) : ptr_m(new int[num]) {};
    ~myvec() { delete ptr_m; }
    void resize(int num) { delete ptr_m; ptr_m = new int[num]; }
    int & operator[] (int i) const { return ptr_m[i]; }
    int *ptr_m;
};

const myvec test(30);
int &a = test[3]; // This is fine, as desired
test.resize(10); // Error here, as expected

因此,std::vector似乎将容器的常数传播到向量的元素,这似乎很奇怪,因为如果我希望元素是常数,我会使用std::vector

无论如何,我如何创建一个std::向量,其大小在构造后不能更改,但其元素可以写入?


共有3个答案

魏翔
2023-03-14

直接的答案是您不能这样做:您不能将向量定义为const,然后向其添加成员。

正如其他人所指出的,新标准提供了array类,它可能更适合您所做的事情。

如果你对固定长度感兴趣,向量中你能感兴趣的最相关的方法是保留(),它将设置向量

如果不能使用Std C 11,那么需要创建一个不允许修改向量的包装器类。例如:

#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;
    }
}

希望这有帮助。

邹修真
2023-03-14
匿名用户

实际的错误是因为您将向量声明为常量,这意味着您永远无法更改内容。

然后,当您尝试获取对向量中条目的非常量引用时,编译器会告诉您不能这样做,因为这样您就可以更改存储在向量中的常量值。

至于创建一个向量,其大小可以在运行时固定,但在创建向量后不改变大小,那么您必须创建一个容器适配器。基本上,你必须在另一个容器周围创建一个包装器,就像std::stack那样。

仰翰采
2023-03-14

如果不编写自己的包装类,这是不可能的。如果您想使用普通的std::向量,您必须依靠自律,不直接或间接使用成员函数插入()push_back()emplace_back()(例如通过back_inserter)。

请注意,对于新的C 14标准,目前有一个关于动态阵列的提案:

[...]我们建议为数组定义一个新的工具,其中元素的数量在构造时是绑定的。我们称这些动态数组为dynarray。

该提案实际上附带了一个参考实现,您可以在自己的代码中使用(请确保暂时将namespace std更改为其他内容)。

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
 类似资料:
  • 问题内容: 我想用Java创建一个Stack,但是要固定大小。例如,创建一个新的堆栈,将大小设置为10,然后在将项目推入堆栈时将其填满,并在将其填满到十时将堆栈中的最后一个项目推出(移出)。我想使用Stack,因为它使用LIFO,非常适合我的需求。 但是Stack从Vector继承的setSize()方法似乎并没有真正限制Stack的大小。我想我缺少有关堆栈如何工作的信息,或者堆栈并不是要受到约束

  • 问题内容: 在Swift中,我试图创建一个由64个SKSpriteNode组成的数组。我想先将其初始化为空,然后将Sprites放在前16个单元格中,然后将最后16个单元格中(模拟象棋游戏)。 根据我在文档中了解的内容,我期望会出现以下情况: 要么 但这是行不通的。在第二种情况下,我收到一条错误消息:“尚不支持定长数组”。那可以是真的吗?对我来说,这听起来像是一项基本功能。我需要通过它们的索引直接

  • 如何创建一个可以容纳10个元素的空列表? 之后,我想在该列表中分配值。例如: 但是,这会导致<code>索引器:列表分配索引超出范围。为什么? 在Python中,列表没有设置的容量,但不可能分配给尚未存在的元素。这里的答案显示了创建一个包含10个“伪”元素的列表的代码,以便稍后替换。然而,大多数遇到这个问题的初学者实际上只是想通过向列表中添加元素来构建列表。这应该使用方法,尽管通常会有特定于问题的

  • 问题内容: 在C ++中,我可以创建如下数组: 在python中,我只知道我可以声明一个列表,而不要附加一些项目或类似。 我可以按给定的大小(如c ++)初始化列表,并且不进行任何赋值吗? 问题答案: (tl;博士:您问题的确切答案是或,但您可能不在乎,可以摆脱使用的困扰。) 您可以将列表初始化为所有相同的元素。使用非数字值在语义上有意义(如果使用它会在以后产生错误,这是一件好事)或类似0的值(不

  • 我正在使用以下代码创建一个围绕JPanel的边框: 创建一个固定的边框不应该这么难,我做错了什么?

  • 我想创建一个包含以下内容的HTML页面: 左侧的固定宽度、全高度导航窗格 剩余区域中心的正方形元素 我希望这个方格尽可能大,扩大以填充导航窗格未占用的区域。 我有一个JavaScript解决方案(见下文和JSFIDLE),但我希望这可以作为一个CSS唯一的解决方案。